单片机 数字电压表设计 - 图文

更新时间:2024-05-11 22:32:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

青岛农业大学

第六届电子设计大赛设计方案

项 目 名 称: 基于单片机数字电压表设计

参 赛 成 员:张银忠 通信10级2班

王恒 通信10级2班

张党顺 通信10级2班 1

基于单片机的数字电压表

摘要:本文介绍一种基于STC89C52单片机的一种电压测量电路,该电路采用运放OP07高精

度、逐步逼近A/D转换电路,测量范围直流0-±2000伏,使用LCD液晶模块显示,可以与PC机进行串行通信。正文着重给出了软硬件系统的各部分电路,介绍了逐步逼近电路的原理,STC89C52的特点,maax197的功能和应用。该电路设计新颖、功能强大、可扩展性强。

关键词:电压测量,运放OP07,逐步逼近式 A/D转换器,12864液晶模块

1.前言

数字电压表(Digital Voltmeter)简称DVM,它是采用数字化测量技术,把连续的模拟量(直流输入电压)转换成不连续、离散的数字形式并加以显示的仪表。传统的指针式电压表功能单一、精度低,不能满足数字化时代的需求,采用单片机的数字电压表,由精度高、抗干扰能力强,可扩展性强、集成方便,还可与PC进行实时通信。目前,由各种单片A/D 转换器构成的数字电压表,已被广泛用于电子及电工测量、工业自动化仪表、自动测试系统等智能化测量领域,示出强大的生命力。与此同时,由DVM扩展而成的各种通用及专用数字仪器仪表,也把电量及非电量测量技术提高到崭新水平。本章重点介绍单片A/D 转换器以及由它们构成的基于单片机的数字电压表的工作原理。

2.系统原理及基本框图 2.1 单片机部分

由于单片机在整个设计中占据着重要的地方,首先介绍一下单片机的相关知识。单片机STC89C52具有低电压供电和体积小等特点,四个端口只需要两个口就能满足电路系统的设计需要。

8051是MCS-51系列单片机的典型产品,我们以这一代表性的机型进行系统的讲解。

8051单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明:

·中央处理器:

中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。 ·数据存储器(RAM)

8051内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。 8051内部结构如图1所示:

图1 8051 内部结构

·程序存储器(ROM):

2

8051共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。 ·定时/计数器(ROM):

8051有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。 ·并行输入输出(I/O)口:

8051共有4组8位I/O口(P0、 P1、P2或P3),用于对外部数据的传输。 ·全双工串行口:

8051内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。 ·中断系统:

8051具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。 ·时钟电路:

8051内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但8051单片机需外置振荡电容。

单片机的结构有两种类型,一种是程序存储器和数据存储器分开的形式,即哈佛(Harvard)结构,另一种是采用通用计算机广泛使用的程序存储器与数据存储器合二为一的结构,即普林斯顿(Princeton)结构。INTEL的MCS-51系列单片机采用的是哈佛结构的形式,而后续产品16位的MCS-96系列单片机则采用普林斯顿结构。

下图是MCS-51系列单片机的内部结构示意图2所示:

图2 MCS-51结构框图

MCS-51的引脚说明:

MCS-51系列单片机中的8031、8051及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明:

3

MCS-51的引脚说明:

MCS-51系列单片机中的8031、8051及8751均采用40Pin封装的双列直接DIP结构,图3是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明:

图3 51单片机引脚图

Pin9:RESET/Vpd复位信号复用脚,当8051通电,时钟电路开始工作,在RESET引脚上出现24个时钟周期以上的高电平,系统即初始复位。初始化后,程序计数器PC指向0000H,P0-P3输出口全部为高电平,堆栈指针写入07H,其它专用寄存器被清“0”。RESET由高电平下降为低电平后,系统即从0000H地址开始执行程序。然而,初始复位不改变RAM(包括工作寄存器R0-R7)的状态,8051的初始态。

8051的复位方式可以是自动复位,也可以是手动复位,见下图。此外,RESET/Vpd还是一复用脚,Vcc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。其复位电路如图4所示:

图4 复位电路图

·Pin30:ALE/当访问外部程序器时,ALE(地址锁存)的输出用于锁存地址的低位字节。而访问内部程序存储器时,ALE端将有一个1/6时钟频率的正脉冲信号,这个信号可以用于识别单片机是否工作,也可以当作一个时钟向外输出。更有一个特点,当访问外部程序存储器,ALE会跳过一个脉

4

冲。

如果单片机是EPROM,在编程其间,将用于输入编程脉冲。 ·Pin29:当访问外部程序存储器时,此脚输出负脉冲选通信号,PC的16位地址数据将出现在P0和P2口上,外部程序存储器则把指令数据放到P0口上,由CPU读入并执行。

·Pin31:EA/Vpp程序存储器的内外部选通线,8051和8751单片机,内置有4kB的程序存储器,当EA为高电平并且程序地址小于4kB时,读取内部程序存储器指令数据,而超过4kB地址则读取外部指令数据。如EA为低电平,则不管地址大小,一律读取外部程序存储器指令。显然,对内部无程序存储器的8031,EA端必须接地。

2.2 模拟电路部分

该方案要求的测量信号电平的动态范围大(0.001~4.99Vrms),频带宽(20Hz~0.2MHz),电压测量误差为土(3%读数+2个字)。由上对AD637性能分析,系统应采用电压输出方式,不宜采用直接dB输出方式,并应具备输如信号增益调节环节,以保证信号电平的动态范围及精度。电平测量的原理框图如图5所示:

信号输可变增益放大器 AD637 模/数转MPU 图5 电平(电压)测量原理框图

下面是对各框图的解说:

(1)可变增益放大电路的设计

由于最小输入信号为毫伏级,系统要求具有输入阻抗变换功能,可变增益放大电路可采用射随器加可变增益放大器的结构形式。由于大多数AD变换器的满刻度输出为5V,增益变换档位应为5V、1V、100mV和10mV4个档位。经实际测量,AD637在输入信号为2MHz以下,信号有效值为0.7~7Vrms范围内能保证无误,当输入电压为200mVrms时,频率上限高达600kHz,考虑到芯片供电与输入电压的关系, AD673输入信号幅度范围选取0.2~2V。所以该可变增益放大电路可采用电阻网络衰减器和固定增益放大器相串联形式,放大器增益不小于200,上述档位对应的衰减器衰减量分别为0.001倍、0.01倍、0.1倍和1倍。

射随器应选择单位增益带宽大于0.6MHz,输入失调电压、失调电流小的运放芯片,可选择OP07单运放芯片。其在土15V供电时,输入失调电压的典型值和最大值分别为20UF和75UF;输入偏置电流的典型值和最大值分别为6NA和12NA;增益带宽积大于0.6MHZ,完全满足设计精度要求。

由于放大器增益至少应大于200,放大器芯片的选择主要考虑输入失调电压、电流和增益带宽参数,选择OP07芯片。其开环在1MHZ时可达50DB,输入失调电压典型值为35UV,失调电流典型值50NA,满足设计要求。

可变增益放器电路的电路图如图6所示。待测电信号由J1输入电路,从TESTV输出。放大电路输入阻抗变换采用拨码开关S2完成。档位选择采用模拟开关芯片CD4052。,MPU根据采样获得的测量值大小,自动完成档位转换。档位在10V时,输入信号首先经R14、R15衰减0.1倍,经射随器后在衰减0.01倍,由CD4052BE切换至200倍放大器U4。由电路图可知,流经所有芯片的信号峰值均小于2V,使整个电路可采用土5V电源供电,既简化了整个系统的电源设计,又兼容了后继处理电路的要求。

5

图6 可变增益放大电路

2.3 有效测量电路的设计

有效测量电路由有效测量芯片AD637和A/D转换芯片ADC0804组成。有效值测量芯片采用后置二阶滤波连接方式,其中的CAV(C1)取值为1UF时满足信号在20H~1MHZ频带范围内的测量精度要求,此时测量时间为365MS,此时间参数可作为采样周期的参考值。在该电路中,由于AD637输出的最小电压幅度为200MV,A/D转换精度应大于8BITS方能在A/D转换的参考电压为5V时满足系统测量误差小于3%的要求。因本系统对A/D转化的采样频率要求高,A/D转换芯片可采用并行输出方式,本电路采用具有8BITS换精度的ADC0804芯片。由于AD637输出的最大电压幅度为2V,A/D转换器的参考电压至少应为5V,选用+5V电源作为参考电压,完全满足系统精度及AD7920供电要求。

电平测量的完整电路图如图7所示。

图7 有效值测量电路

2.4 A/D 转换电路的设计

6

2.4.1 MAX197转换的基本原理

MAX197无需外接元器件就可独立完成A/D转换功能。它可分为内部采样模式和外部采样模式,采样模式由控制寄存器的D5位决定。在内部采样控制模式(控制位置0)中,由写脉冲启动采样间隔,经过瞬间的采样间隔(芯片时钟为2MHz时,为3ms),即开始A/D转换。在外部采样模式(D5=1)中,由两个写脉冲分别控制采样和A/D转换。在第一个写脉冲出现时,写入ACQMOD为1,开始采样间隔。在第二个写脉冲出现时,写入控制字ACQMOD为0,MAX197停止采样,开始A/D转换。这两个写脉冲之间的时间间隔为一次采样时间。当一次转换结束后,MAX197相应的INT引脚置低电平,通知处理器可以读取转换结果。

A/D 转换器的转换精度对测量电路极其重要,它的参数关系到测量电路性能。本设计采用逐步逼近式A/D 转换器,它的性能比较稳定,转换精度高,具有很高的抗干扰能力,电路结构简单,其缺点是工作速度较低。在对转换精度要求较高,而对转换速度要求不高的场合如电压测量有广泛的应用。

2.4.2 逐步逼近式A/D转换器的工作原理

逐步逼近式A/D转换器的工作原理图,如图8所示: V N V V D/A转换器 IN REF D7

D6 锁 D5 START存 D4

缓 D3/D11 控制 存 D2/D10 逻辑 器 D1/D9 D0/D8

EOC N位寄存器 OE 图8 A/D工作原理图

2.4.3 max197的应用 ADC0804的规格及引脚图

8 位COMS 依次逼近型的A/D 转换器. 三态锁定输出 存取时间:135US 分辨率:8位

转换时间:100US 总误差:正负1LSB

工作温度:ADC0804LCN---0~70度

7

信 号 输 出 端 电 压 输 入

2.5 液晶显示部分

2.5.1液晶介绍

12864M是一种图形液晶显示器,它主要由行驱动/列驱动和128*64全点阵液晶显示器组成。可完成图形显示,也可显示8*4个(16*16点阵)汉字。

1、电源:VDD+5V,模块内自带-10V负压,用于LCD的驱动。 2、显示内容:128(列)*64(行)点。 3、七种指令。

4、与CPU接口采用8位数据总线并行输入输出和8条控制线。 5、工作温度:0-60。

2.6 无线传输部分

2.6.1 NRF905的基本原理

nRF905可以自动完成处理字头和CRC(循环冗余码校验)的工作,可由片内硬件自动完成曼彻斯特编码/解码,使用SPI接口与微控制器通信,配置非常方便,其功耗非常低,以-10dBm的输出

8

功率发射时电流只有11mA,在接收模式时电流为12.5mA。 nRF905单片无线收发器工作由一个完全集成的频率调制器,一个带解调器的接收器,一个功率放大器,一个晶体震荡器和一个调节器组成。ShockBurst工作模式的特点是自动产生前导码和CRC,可以很容易通过SPI接口进行编程配置。

2.6.2 NRF905的工作模式 nRF905采用Nordic公司的VLSI ShockBurst技术。ShockBurst技术使nRF905能够提供高速的数据传输,而不需要昂贵的高速MCU来进行数据处理/时钟覆盖。通过将与RF协议有关的高速信号处理放到芯片内,nRF905提供给应用的微控制器一个SPI接口,速率由微控制器自己设定的接口速度决定。nRF905通过ShockBurst工作模式在RF以最大速率进行连接时降低数字应用部分的速度来降低在应用中的平均电流消耗。在ShockBurst RX模式中,地址匹配AM和数据准备就绪DR信号通知MCU一个有效的地址和数据包已经各自接收完成。在ShockBurst TX模式中,nRF905自动产生前导码和CRC校验码,数据准备就绪DR信号通知MCU数据传输已经完成。总之,这意味着降低MCU的存储器需求也就是说降低MCU成本,又同时缩短软件开发时间。

1)、典型ShockBurst TX模式: ①、当应用MCU有遥控数据节点时,接收节点的地址TX-address和有效数据TX-payload通过SPI接口传送给nRF905应用协议或MCU设置接口速度;

②、MCU设置TRX_CE、TX_EN为高来激活nRF905 ShockBurst传输; ③、nRF905 ShockBurst: 无线系统自动上电?

数据包完成(加前导码和CRC校验码)?

数据包发送(100kbps,GFSK,曼? 切斯特编码) CRC

④、如果AUTO_RETRAN被设置为高nRF905将连续地发送数据包直到TRX_CE被设置为低; ⑤、当TRX_CE被设置为低时,nRF905结束数据传输并自动进入standby模式。 2)、典型ShockBurst RX模式

①、通过设置TRX_CE高,TX_EN低来选择ShockBurst模式; ②、650us以后,nRF905监测空中的信息;

③、当nRF905发现和接收频率相同的载波时,载波检测CD被置高; ④、当nRF905接收到有效的地址时,地址匹配AM被置高;

⑤、当nRF905接收到有效的数据包(CRC校验正确)时,nRF905去掉前导码、地址和位,数据准备就绪(DR)被置高;

⑥、MCU设置TRX_CE低,进入standby模式低电流模式;

⑦、MCU可以以合适的速率通过SPI接口读出有效数据; ⑧、当所有的有效数据被读出后,nRF905将AM和DR置低;

⑨、nRF905将准备进入ShockBurst RX、ShockBurst TX或Powerdown模式。 3)、掉电模式

在掉电模式中,nRF905被禁止,电流消耗最小,典型值低于2.5uA。当进入这种模式时,nRF905是不活动的状态。这时候平均电流消耗最小,电池使用寿命最长。在掉电模式中,配置字的内容保持不变。

9

显示,图像如下

2.6.3 NRF905的电路连接

三.模块主要硬件构成说明

12864液晶显示结构框图,如图11所示:

图11 12864结构框图

四.显示界面设置

(1)开机显示界面采用12864图像显示处理,通过图像处理得到128*64大小的图像,获取代码

10

(2)电压测试界面,主显示界面采用的是软件控制,主要代码

uchar code dis1[]={\量A 10MV C 100MV%uchar code dis2[]={\程B 1V D 10V%uchar code dis3[]={\所选量程:%uchar code dis4[]={\测值:%uchar code dis5[]={\当前室温:%uchar code dis6[]={%uchar code dis7[]={\

uchar code dis8[]={\量程错误!!void disphoto(uchar *photo) //{

unsigned char i,j;

writecmd(0x34); // for(i=0;i<32;i++) {

writecmd(0x80+i); //

writecmd(0x80); //

for(j=0;j<16;j++) // {

writedat(*photo++); delay2(1); } }

for(i=0;i<32;i++) {

writecmd(0x80+i); writecmd(0x88);

for(j=0;j<16;j++) {

writedat(*photo++); delay2(1); }

\

图片显示 关闭绘图 垂直坐标 水平坐标 一行可显示16个字符11

}

writecmd(0x36); } }

显示如图

量 A 10mV B 1V 程 C 100mV D 5V 所选量程: 测值为:

(3)温度显示界面

通过判断当前温度,显示提示语言:1室温偏高注意防暑2室温适宜注意休息3根据温差谨防感冒

四. 系统软件设计 4.1主程序设计

室内温度 T:xxxx *主菜单* 12

主程序 主显示界面 测压界面 温度 If u>10mv If u>100mv If u>1v If u>5v T<20℃ 20℃T>31℃ 提示量程选择错误 提示语言 提示语言 提示语言

13

4.2程序清单

主程序代码:

#include #include #include #include

#define uchar unsigned char #define uint unsigned int sbit rs=P3^0; sbit rw=P3^1; sbit en=P3^4; sbit psb=P3^5;

sbit int1=P3^3;//定义管脚功能 sbit cs=P3^2;//定义ADcs端

sbit a1=P2^6;//定义CD4052的A端口 sbit b1=P2^7 ;//定义CD4052的B端口 sbit wr=P3^6; sbit rd=P3^7;

unsigned int dianya,count,aaa,aaa_h; unsigned int dianyah,dianyal; //用于存储读出数据的高字节和低字节 unsigned char addata,i; unsigned int dianya=0;

const uchar table[]={0x30,0x31,0x32,0x33, 0x34,0x35,0x36,0x37, 0x38,0x39,0x41,0x42, 0x43,0x44,0x45,0x46};

uchar code dis1[]={\量A 10mV B 1V %uchar code dis2[]={\程C 100mV D 5V%uchar code dis3[]={\所选量程:%uchar code dis4[]={\测值:\

uchar code dis5[]={\当前室温:%uchar code dis6[]={%uchar code dis7[]={\

uchar code dis8[]={\量程错误!!%uchar code dis9[]={\室温偏高注意防暑%uchar code dis10[]={\室温适宜注意休息%uchar code dis11[]={\根据温差谨防感冒%uchar code dis12[]={\请选择量程%unsigned char code photo1[]= {

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

14

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x2F,0xE3,0xF8,0x00,0xF0,0x07,0x8F,0x07,0xBC,0x1E,0x03,0xFE,0x7F,0x00,0x00, 0x00,0x07,0xFF,0xFC,0x0F,0xF0,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xC0,0x00, 0x00,0x3F,0xFF,0xFE,0x0F,0xF0,0x00,0x0F,0xFF,0x7F,0xFF,0xFF,0x9F,0xE7,0xC0,0x00, 0x00,0x3F,0x3F,0x9C,0x0F,0xE0,0x00,0x07,0xFE,0x3F,0xFF,0xFC,0x1F,0xC1,0xC0,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x03,0xC1,0xE0,0x00,0xF0,0x00,0x0F,0x00,0x00,0x00,0x00,0x03,0xE0,0x00,0x00, 0x00,0x1F,0xD9,0xE0,0x01,0xF0,0x00,0x0F,0x00,0x1F,0xFF,0xFC,0x01,0xC0,0x00,0x00, 0x00,0x1D,0xFD,0xC1,0xFF,0xFF,0xF0,0x0F,0x00,0x1F,0xFF,0xFD,0xFF,0xFF,0xC0,0x00, 0x00,0x1F,0xFB,0xC1,0xFF,0xFF,0xF7,0xFF,0xFE,0x1F,0xFF,0xFD,0xFF,0xFF,0xC0,0x00, 0x00,0x0D,0xDB,0xFE,0xFF,0xFF,0xF7,0xFF,0xFE,0x1E,0x00,0x00,0x01,0xC0,0x00,0x00, 0x00,0x3F,0xFF,0xFE,0xE0,0x00,0xF7,0xFF,0xFE,0x1E,0x1E,0x00,0x01,0xC0,0x00,0x00, 0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xF7,0x8F,0x1E,0x1E,0x1E,0x01,0xFF,0xFF,0x80,0x00, 0x00,0x07,0xC7,0x9C,0x1F,0xFF,0x07,0x8F,0x1E,0x1E,0x1E,0x01,0xFF,0xFF,0x80,0x00, 0x00,0x1F,0xFF,0x9C,0x1F,0xFF,0x07,0xFF,0xFE,0x1E,0x1E,0x00,0x01,0xC0,0x00,0x00, 0x00,0x3D,0xFF,0x9C,0x00,0x3E,0x07,0xFF,0xFE,0x1F,0xFF,0xF8,0x01,0xC0,0x00,0x00, 0x00,0x3F,0xDF,0xBC,0x00,0xF8,0x07,0x8F,0x1E,0x1F,0xFF,0xFB,0xFF,0xFF,0xC0,0x00, 0x00,0x17,0x87,0xFD,0xFF,0xFF,0xF7,0x8F,0x1E,0x1D,0xFF,0xFB,0xFF,0xFF,0xC0,0x00, 0x00,0x3F,0xF9,0xF9,0xFF,0xFF,0xF7,0xFF,0xFE,0x1E,0x1E,0x00,0x0F,0xE3,0x80,0x00, 0x00,0x3F,0xF9,0xF9,0xFF,0xFF,0xF7,0xFF,0xFE,0x3C,0x1E,0x60,0x3E,0xFF,0xC0,0x00, 0x00,0x0E,0x78,0xF0,0x00,0xF0,0x07,0xFF,0xFF,0x3C,0x1F,0xF8,0x7E,0xFF,0x40,0x00, 0x00,0x1F,0xF0,0xF0,0x00,0xF0,0x07,0x8E,0x07,0xBC,0x1E,0x71,0xFE,0x7C,0x00,0x00,

0x00,0x18,0x06,0x0C,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x1C,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x38,0x78,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x3C,0x07,0x0E,0x00,0x78,0x78,0x1F,0xFF,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x7F,0xF8,0x0F,0xFF,0xFE,0x7F,0xFF,0xDF,0xFF,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x7F,0xFF,0xF7,0xFF,0xFE,0x7F,0xFF,0xDE,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x07,0xFF,0xF7,0xFB,0xDE,0xF0,0x78,0x1E,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x37,0xF0,0xF3,0xFB,0xDE,0xF0,0x78,0x1E,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x7F,0xF0,0xF0,0x7B,0xDE,0xFF,0xFF,0x9F,0xFF,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFB,0xDF,0xFF,0xFF,0x9F,0xFF,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x3F,0x6F,0xEF,0xFB,0xDF,0xFF,0x7B,0x9E,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x1F,0x1E,0x07,0xFF,0xDF,0xFF,0x7B,0x9E,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x1F,0x1F,0x07,0xFF,0xDF,0xFF,0xFF,0x9E,0x3C,0xF0,0x00,0x00,0x00,

2

0x00,0x00,0x00,0x1F,0x1F,0x07,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x1F,0xBF,0x87,0xFF,0xFC,0x77,0x7B,0x9F,0xFF,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x3F,0xFF,0x87,0xB3,0xC0,0x77,0xF8,0x1E,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x3F,0x7F,0xC7,0x83,0xC0,0x73,0xF0,0x1E,0x3C,0xF0,0x00,0x00,0x00, void delay1(unsigned int z);//定义读书延时函数

void delay2(unsigned int t); void delayNOP();

void lcdpos(uchar X,uchar Y);

void writecmd(unsigned char cmd); //写命令

void writedat(unsigned char dat); 0x00,0x00,0x00,0x79,0xF9,0xE7,0xC0,0x00,0x73,0xFC,0x1E,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x73,0xF1,0xFF,0xFF,0xFE,0x7F,0xFF,0xFE,0x3C,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x70,0xC0,0x6E,0xFF,0xFE,0x7F,0x0F,0xBC,0x3F,0xF0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x00,0x1C,0x3F,0xE0,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

unsigned char num,temp;//定义键盘返回值,中间变量

unsigned char getkey();//键盘扫描函数 unsigned char adc0804(void); //读AD0804子程序 //读AD0804子程序

unsigned int datpro(void);//ADC0804读出的数据处理

//写数据

void init(); //初始化 bit busy();

void displayA(); void displayB(); void displayC(); void displayD();

void disphoto(unsigned char *photo); //图片显示

void display_jiemian();

void clear(); //清屏 void display1(); void display(); void main() {

delay2(100); init();

disphoto(photo1); delay1(2000); clear(); delay2(5);

display_jiemian(); num=6; while(1) {

if(num==1) {

getkey();//获得键盘输入值

if(num==2||num==3||num==5||num==6) {

num=1; }

switch(num) {

3

case 2:a1=0;b1=0; break; case 5:a1=1;b1=0; break; case 3:a1=0;b1=1; break; default:a1=1;b1=1; }; display1(); } if(num==4) { getkey();//获得键盘输入值 switch(num) { case 2:a1=0;b1=0; break; case 5:a1=1;b1=0; break; case 3:a1=0;b1=1; break; default:a1=1;b1=1; }; lcdpos(3,3); for(i=0;i<10;i++) { writedat(dis12[i]); delay1(1); } display_jiemian(); delay1(5); } if(num==2)//(条件选择语句)不同的档位不同的显示形式

{ getkey();//获得键盘输入值 switch(num) { case 2:a1=0;b1=0; break; case 5:a1=1;b1=0; break; case 3:a1=0;b1=1; break; default:a1=1;b1=1; }; lcdpos(2,6); writedat('A'); delay1(2); lcdpos(3,7); for(i=0;i<2;i++) { writedat(dis6[i]); delay1(1); } adc0804();//读取模数转换数据 aaa=datpro();//读电压 if(aaa>=40000) { display(); delay1(1); } else { displayA(); delay1(2); } } if(num==3)

4

{ getkey();//获得键盘输入值 switch(num) { case 2:a1=0;b1=0; break; case 5:a1=1;b1=0; break; case 3:a1=0;b1=1; break; default:a1=1;b1=1; }; lcdpos(2,6); writedat('B'); delay1(2); lcdpos(3,7); for(i=0;i<2;i++) { writedat(dis7[i]); delay1(1); } delay1(2); adc0804();//读取模数转换数 aaa=datpro();//读电压据 if(aaa>=40000) { display(); delay1(1); } else { displayB(); delay1(2); } }

if(num==5) { getkey();//获得键盘输入值 switch(num) { case 2:a1=0;b1=0; break; case 5:a1=1;b1=0; break; case 3:a1=0;b1=1; break; default:a1=1;b1=1; }; lcdpos(2,6); writedat('C'); delay1(2); lcdpos(3,7); for(i=0;i<2;i++) { writedat(dis6[i]); delay1(1); } delay1(2); adc0804();//读取模数转换数据 aaa=datpro();//读电压 if(aaa>=40000) { display(); delay1(1); } else { displayC(); delay1(2); }

5

} if(num==6) { getkey();//获得键盘输入值 switch(num) { case 2:a1=0;b1=0; break; case 5:a1=1;b1=0; break; case 3:a1=0;b1=1; break; default:a1=1;b1=1; }; lcdpos(2,6); writedat('D'); delay1(2); lcdpos(3,7); for(i=0;i<2;i++) { writedat(dis7[i]); delay1(1); } delay1(2); adc0804();//读取模数转换数据 aaa=datpro();//读电压 if(aaa>=40000) { display(); delay1(1); } else { displayD(); delay1(2); }

} } } unsigned char getkey(void) { P2=0xf7; temp=P2; temp=temp&0xe7; while(temp!=0xe7) { delay1(5); temp=P2; temp=temp&0xe7; while(temp!=0xe7) { switch(temp) { case 0xe3:num=3; break; case 0xe5:num=2;

break; case 0xe6:num=1; break; } while(temp!=0xe7) //松手检测 { temp=P2; temp=temp&0xe7; } } } P2=0xef; temp=P2; temp=temp&0xe7; while(temp!=0xe7) { delay1(5);

6

temp=P2;

temp=temp&0xe7; while(temp!=0xe7) {

switch(temp) {

case 0xe3:num=6;

break; case 0xe5:num=5;

break; case 0xe6:num=4;

break; }

while(temp!=0xe7) //松手检测

{

temp=P2; temp=temp&0xe7;

} } } return(num); }

unsigned char adc0804( void ) {

rd=1; wr=1; int1=1;

P1=0xff; cs=0; wr=0; wr=1;

while(int1==1); rd=0; delay1(1); addata=P1; rd=1; cs=1;

return(addata);

}

unsigned int datpro(void) {

unsigned char x;

for(x=0;x<10;x++) {

dianya=addata+dianya; }

dianya=dianya/10; dianya=addata;

dianyah=dianya&0xf0; dianyah=dianyah>>4; dianyal=dianya&0x0f;

dianya=dianyal+dianyah*16; aaa=dianya*195.3125; return(aaa); }

void delay1(unsigned int z) {

uint t1,y;

for(t1=z;t1>0;t1--) {

for(y=110;y>0;y--); } }

void delay2(unsigned int t) {

uchar i,j;

for(i=0;i

void delayNOP() {

_nop_(); _nop_(); _nop_(); _nop_(); }

bit busy() {

bit i; rs=0; rw=1; en=1;

7

delayNOP();

i=(bit)(P0&0x80); en=0;

return(i); }

void writecmd(unsigned char cmd) writecmd(0x01); delay2(5); }

void lcdpos(uchar X,uchar Y) { uchar pos; if(X==0) {

{

while(busy()); rs=0; rw=0; en=0; _nop_(); _nop_(); P0=cmd; delayNOP(); en=1;

delayNOP(); en=0; }

void writedat(unsigned char dat) {

while(busy()); rs=1; rw=0; en=0; _nop_(); _nop_(); P0=dat; delayNOP(); en=1;

delayNOP(); en=0; }

void init() {

psb=1; delay2(3);

writecmd(0x34); delay2(10);

writecmd(0x30); delay2(10);

writecmd(0x0c); delay2(10);

X=0x80; }

if(X==1) {

X=0X90; }

if(X==2) {

X=0X88; }

if(X==3) {

X=0x98; }

pos=X+Y;

writecmd(pos); }

void disphoto(uchar *photo) //图片显示 {

unsigned char i,j;

writecmd(0x34); //关闭绘图

for(i=0;i<32;i++) {

writecmd(0x80+i); //垂直坐标

writecmd(0x80); //平坐标

for(j=0;j<16;j++) //一行可显示16个字符 {

writedat(*photo++); delay2(1); }

水8

} for(i=0;i<6;i++) //测值: 共 for(i=0;i<32;i++) { writecmd(0x80+i); writecmd(0x88); for(j=0;j<16;j++) { writedat(*photo++); delay2(1); } } writecmd(0x36); } void display_jiemian() { uchar i; lcdpos(0,0); for(i=0;i<17;i++) //量程: 共有6个字符 { writedat(dis1[i]); delay1(1); } lcdpos(1,0); for(i=0;i<14;i++) //量程: 共有6个字符 { writedat(dis2[i]); delay1(1); } lcdpos(2,0); for(i=0;i<10;i++) //所选量程:共有10个字符 { writedat(dis3[i]); delay1(1); } lcdpos(3,0);

有6个字符 { writedat(dis4[i]); delay1(1); } } void clear() { writecmd(0x34); delay1(5); writecmd(0x30); delay1(5); writecmd(0x01); delay1(5); } void displayB() { if(aaa<400) { aaa=0; } aaa=aaa*1.0146; aaa=aaa/4.0; aaa_h=aaa/100.00; writecmd(0x9B); writedat('U'); writedat(':'); writedat(table[(aaa_h/100)]); writedat('.'); writedat(table[(aaa_h/10)]); writedat(table[(aaa/100)]); writedat(table[(aaa/10)]); writedat(table[(aaa/1)]); writecmd(0xdf); writecmd(0x02); delay1(50); } void displayD() { if(aaa<400) { aaa=0;

9

}

aaa=aaa*1.1012; aaa=aaa/4.0;

aaa_h=aaa/100.00; writecmd(0x9B); writedat('U'); writedat(':'); writedat(' ' );

writedat(table[(aaa_h/10)]); writedat('.');

writedat(table[(aaa_h)]); writedat(table[(aaa/10)]); writedat(table[aaa]); writecmd(0xdf); writecmd(0x02); delay1(50); }

void displayA() {

if(aaa<400) {

aaa=0; }

aaa=aaa*1.02; aaa=aaa/4.0;

aaa_h=aaa/100.00; writecmd(0x9B); writedat('U'); writedat(':'); writedat(' ');

writedat(table[(aaa_h/10)]); writedat('.');

writedat(table[(aaa_h/1)]); writedat(table[(aaa/10)]); writedat(table[(aaa/1)]); writecmd(0xdf); writecmd(0x02); delay1(50); }

void displayC() {

if(aaa<1300) {

aaa=0;

}

aaa=aaa*1.0638; aaa=aaa/4; aaa_h=aaa/100; writecmd(0x9B); writedat('U'); writedat(':'); writedat(' ');

writedat(table[(aaa_h/10)]); writedat(table[(aaa_h)]); writedat('.');

writedat(table[(aaa/10)]); writedat(table[(aaa/1)]); writecmd(0xdf); writecmd(0x02); delay1(50); }

void display1() {

uchar a,b; a=0xA1; b=0xE6; ds_getT();

writecmd(0x01); lcdpos(0,0);

for(i=0;i<10;i++) {

writedat(dis5[i]); delay1(1); }

writecmd(0x90); writedat('T'); writedat(':'); writedat(' ' );

writedat(table[(TemH/10)]); writedat(table[TemH]); writedat('.');

writedat(table[(count/10)]); writedat(table[count]); writedat(a); writedat(b); if(TemH>=30) {

lcdpos(3,0);

10

for(i=0;i<17;i++) {

writedat(dis9[i]); delay1(1); } }

if(TemH<=30&&TemH>=20) {

lcdpos(3,0); for(i=0;i<17;i++) {

writedat(dis10[i]); delay1(1); } }

if(TemH<=20) {

lcdpos(3,0); for(i=0;i<17;i++) {

writedat(dis11[i]); delay1(1); } }

writecmd(0xdf); writecmd(0x02); delay1(500); }

void display() {

lcdpos(3,3);

for(i=0;i<8;i++) {

writedat(dis8[i]); delay1(1); } }

/*ds18b20.h*/

#define BUSY1 (DQ1==0) 义busy信号

//定

sbit DQ1=P2^5; //定义18B20单总线引脚

void ds_reset_1(void); //声明18B20复位函数

void wr_ds18_1(char dat); //声明18B20写入函数

void time_delay(unsigned char time);//声明延时函数

int get_temp_1(void); //声明18B20读入温度函数

void delay(unsigned int x); //声明延时函数

void read_ROM(void); //声明18B20读ROM函数

int get_temp_d(void); //声明获取温度函数

void ds_init(void); //声明18B20初始化函数

void ds_getT(void); //声明18B20获得温度显示值函数

/****************以下定义各种变量********************/

unsigned char ResultSignal; int

ResultTemperatureLH,ResultTemperatureLL,ResultTemperatureH; unsigned char ROM[8]; unsigned char idata TMP; unsigned char idata TMP_d; unsigned char f;

unsigned char rd_ds18_1();

unsigned int TemH,TemL; //温度的整数部分和小数部分

unsigned int count; //定义小数计算部分

/***********************延时程序=a*1ms**************************************/

void delay111(unsigned char a) {

unsigned char i; while(a-- !=0)

11

{

/* reset ds18b20 for(i=0;i<80;i++); } }

void ds_init(void) {

unsigned int k=0; ds_reset_1();

ds_reset_1(); //reset wr_ds18_1(0xcc); //skip rom

_nop_();

wr_ds18_1(0x7f); ds_reset_1(); wr_ds18_1(0xcc); _nop_();

wr_ds18_1(0x44);

for(k=0;k<11000;k++)

time_delay(255); ds_reset_1(); }

void ds_getT(void) {

wr_ds18_1(0xcc); wr_ds18_1(0xbe); TemH=get_temp_1(); TemL=get_temp_d(); TemH&=0x00ff; TemL&=0x00ff;

count=(TemH*256+TemL)*6.25; }

/***************延时程序,单位us,大于10us*************/

void time_delay(unsigned char time) {

time=time-10; time=time/6;

while(time!=0)time--; }

/*****************************************************/

*/

/*****************************************************/

void ds_reset_1(void) {

unsigned char idata count=0; DQ1=0;

time_delay(240); time_delay(240); DQ1=1; return; }

void check_pre_1(void) {

while(DQ1); while(~DQ1);

time_delay(30); }

void read_ROM(void) {

int n;

ds_reset_1(); check_pre_1(); wr_ds18_1(0x33);

for(n=0;n<8;n++){ROM[n]=rd_ds18_1();} }

/*****************************************************/

/* Read a bit from 1820 位读取*/

/*****************************************************/ bit tmrbit_1(void) {

idata char i=0;

12

bit dat;

DQ1=0;_nop_();

DQ1=1; _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();

dat = DQ1;

time_delay(50);

return dat; }

/*****************************************************/

/* read a bety from ds18b20 字节读取 */

/*****************************************************/

unsigned char rd_ds18_1() {

unsigned char idata i,j,dat=0; for(i=1;i<=8;i++) {

j=tmrbit_1();

dat=(j<<(i-1))|dat; }

return dat; }

/*****************************************************/

/* write a bety from ds18b20 写字节 */

/****************************************************/

void wr_ds18_1(char dat) {

signed char idata i=0; unsigned char idata j; bit testb;

for(j=1;j<=8;j++) {

testb=dat & 0x01; dat = dat>>1; if(testb) {

DQ1=0; _nop_(); _nop_(); DQ1=1; time_delay(60); }

else {

DQ1=0;

time_delay(50);

DQ1=1; _nop_(); _nop_(); } } }

13

int get_temp_1(void) {

unsigned char idata a=0,b=0; unsigned char idata i; EA=0;

TMP=~TMP; TMP=(TMP+1); } EA=1;

return(TMP); }

int get_temp_d(void) {

unsigned char idata a=0,b=0; ds_reset_1(); check_pre_1();

wr_ds18_1(0xcc); wr_ds18_1(0x44); while(BUSY1);

ds_reset_1(); check_pre_1();

wr_ds18_1(0xcc); wr_ds18_1(0xbe);

a=rd_ds18_1(); b=rd_ds18_1();

i=b; /*若b为1则为负温 i=(i>>4); if(i==0) {

f=0;

TMP=((a>>4)|(b<<4)); a=(a&0x0f); if (a>8) {

TMP=(TMP+1); } } else {

f=1; a=a>>4; b=b<<4; TMP=(a|b);

unsigned char idata i,m; EA=0;

ds_reset_1();//复位 check_pre_1();

wr_ds18_1(0xcc); wr_ds18_1(0x44); while(BUSY1);

ds_reset_1(); check_pre_1();

wr_ds18_1(0xcc); wr_ds18_1(0xbe);

a=rd_ds18_1(); b=rd_ds18_1();

i=b; /*若b为1则为负温i=(i>>4);

if(i==0) {

f=0;

TMP=((a>>4)|(b<<4)); a=(a&0x0f); TMP_d=a; } else {

f=1; a=~a; a=(a+1); b=~b;

14

*/ */

}

b=(b+1); m=a; a=a>>4; b=b<<4;

TMP=(a|b); m=(m&0x0f); TMP_d=m;

EA=1;

return(TMP_d); }

void delay(unsigned int x) {

unsigned int i; for(i=0;i

五.参考文献

[1] 徐爱钧.《智能化测量控制仪表原理与设计》(第二版)[M].北京:北京航空航天大学出版社,2004.

[2] 吴金戌,沈庆阳,郭庭吉.《8051单片机实践与应用》[M].北京:清华大学出版社,2002. [3] 张国勋,《缩短ICL7135A/D采样程序时间的一种方法》[J]. 《电子技术应用》,1993,第一期.

[4] 高峰,《单片微型计算机与接口技术》[M].北京:科学出版社,2003. [5] 刘伟,赵俊逸,黄勇,《一种基予C8051F单片机的SOC型数据采录器的设计与实现》[A].天津市计算机学会单片机分会编. 《2003年全国单片机及嵌如入式系统学术年会论文集(下册)》[C] .北京:北京航空航天大学出版社,2003 .790-794

电路原理图:

15

2

3

4

本文来源:https://www.bwwdw.com/article/s06g.html

Top