多路数字电压表的设计(9页).doc
-8.3 多路数字电压表的设计数字电压表是电子测量中经常用到的电子器件,传统的指针式电压表功能单一、精度低、不能满足数字时代的要求。而采用单片机的数字电压表精度高、抗干扰能力强、可扩展性强、使用方便,在日常生活中广泛应用。8.3.1 多路数字电压表的功能要求多路数字电压表的功能要求如下:(1) 输入电压为8路。(2) 电压值的范畴为05V。(3) 测量的最小分辨率为0.019V,测量误差为±0.02V。(4) 能通过显示器显示通道和通道电压,有效位数为小数点后两位8.3.2 多路数字电压表的总体设计多路数字电压表的总体结构如图8.9所示,处理过程如下:先用A/D转换器对各路电压值进行采样,得到相应的数字量,再按数字量与模拟量成正比关系运算得到对应的模拟电压值,然后把模拟值通过显示器显示出来,另外可以通过按键选择通道。51单片机时钟电路复位电路LCD按键ADC0808图8.9 多路数字电压表的总体结构图根据系统的功能要求,控制系统采用AT89C52单片机,A/D转换器采用ADC0808(0809)。ADC0808(0809)是8位的A/D转换器。当输入电压为5.00V时,输出的数据值为255(0FFH),因此最大分辨率为0.0196V(5/255)。ADC0808(0809)具有8路模拟量输入端口,通过3位地址输入端能从8路中选择一路进行转换。如每隔一段时间依次轮流改变3位地址输入端的地址,就能依次对8路输入电压进行测量。显示器采用LCD显示器,显示效果好。按键可只设定一个,用于选择显示的当前通道。8.3.3 多路数字电压表硬件电路多路数字电压表具体硬件电路如图8.10所示。图8.10 多路数字电压表的电路原理图其中,ADC0808(0809) 的数据线D0D7与AT89C52的P2口相连,地址输入端ADDA、ADDB、ADDC与AT89C52的P3口的低3位P3.0、P3.1、P3.2相连,地址锁存控制端ALE和启动信号START连接在一起与P3.7相连,数据输出允许控制端OE与P3.6相连,转换结束信号EOC与P1.3相连。ADC0809的时钟信号输入端CLOCK与P1.4相连,而P1.4由定时/计数器0控制,每10ms取反一次,则CLOCK的时钟周期为20ms,频率为50KHz,满足ADC0808(0809)的时钟要求。参考电压VREF+接+5V电源,参考电压VREF-接地,则当输入电压为5.00V时,输出的数据值为255(0FFH),当输入电压为0V时,输出的数据值为0(00H),最大分辨率为0.0196V(5/255)。显示器LCD1602的数据线与89C 52的P0口相连,RS与P1.7相连,R/与P1.6相连,E端与P1.5相连。按键只设定了一个K1,与AT89C52的P1.0,用于进行通道选择,当按下一次,通道加1,显示下一个通道。8.3.4 多路数字电压表软件程序多路数字电压表系统软件程序由主程序、A/D转换子程序和显示驱动程序组成,这里只介绍主程序、A/D转换子程序。1主程序主程序流程如图8.11所示。首先是对定时计数器和LCD初始化,在LCD上显示提示信息,然后进入循环,在循环中依次为:调用A/D转换子程序对8个通道转换一次,判通道键是否按下,按下则当前通道地址加1,当前通道值转换成电压值,显示当前通道。2A/D转换子程序A/D转换子程序用于对ADC0808的8路输入模拟电压进行一次A/D转换,并将转换的数值存入8个相应的存储单元中,流程图如图8.12所示。A/D转换子程序每隔一定时间调用一次,即隔一段时间对输入电压采样一次。 图8.11 主程序流程 图8.12 A/D转换子程序流程3汇编语言源程序清单;30H37H存放转换的数字量;38H3BH分别放电压当前通道电压的个位、小数点后1位、小数点后2位;3CH单片为通道计数器RS BIT P1.7;定义LCD1602端口线RW BIT P1.6E BIT P1.5STBITP3.7;定义0808控制线OEBITP3.6EOCBITP1.3CLKBITP1.4KEY1BIT P1.0;通道选择按键ORG0000HLJMPMAINORG000BHCPLCLK; 定时/计数器0中断,产生转换时钟RETIORG 50H;主程序MAIN:MOV SP,#50HMOV39H,#'.'MOVTMOD,#02HMOVTH0,#246MOVTL0,#246SETBET0SETBEASETBTR0LCALLDL10MSACALL INITMOV A,#81H;写入显示缓冲区起始地址为第1行第1列ACALL WC51RMOV A,#'A' ;第1行第2列显示字母'H'ACALL WC51DDRMOV A,#'D' ;第1行第3列显示字母"O"ACALL WC51DDRMOV A,#'D' ;第1行第4列显示字母'W'ACALL WC51DDRMOV A,#'R' ;第1行第5列显示字母'U'ACALL WC51DDRMOV A,#':' ;第2行第6列显示字母'!'ACALL WC51DDRMOV A,#0C0H ;写入显示缓冲区起始地址为第2行第5列ACALL WC51RMOV A,#'V' ;第2行第5列显示字母'A'ACALL WC51DDRMOV A,#'A' ;第2行第6列显示字母'R'ACALL WC51DDRMOV A,#'L' ;第2行第7列显示字母'E'ACALL WC51DDRMOV A,#'U' ;第2行第8列显示字母' 'ACALL WC51DDRMOV A,#'E' ;第2行第9列显示字母'Y'ACALL WC51DDRMOV A,#':' ;第2行第10列显示字母'O'ACALL WC51DDRLOOP:LCALLTEST;调用ADC0808转换程序8个通道转换一次JBKEY1,NEXT;有键按下,当前通道地址加1WAIT2:JNBKEY1,WAIT2INC3CHMOVA,3CHCJNEA,#08,NEXTMOV3CH,#00NEXT:MOVA,#30H;取出当前通道值,转换成电压值所对应的字符ADDA,3CHMOVR0,AMOVA,R0MOVB,#51DIVABADDA,#30HMOV38H,AMOVA,BCLRF0SUBBA,#1AHMOVF0,CMOVA,#10MULABMOVB,#51DIVABJBF0,LOOP2ADDA,#5LOOP2:ADDA,#30HMOV3AH,AMOVA,BCLRF0SUBBA,#1AHMOVF0,CMOVA,#10MULABMOVB,#51DIVABJBF0,LOOP3ADDA,#5LOOP3:ADDA,#30HMOV3BH,AMOV A,#88H;写入显示缓冲区起始地址为第1行第9列ACALL WC51RMOVA,3CHADDA,#30H;第1行第9列显示通道号ACALL WC51DDRMOV A,#0C8H;写入显示缓冲区起始地址为第2行第9列ACALL WC51RMOVA,38H;第2行第9列显示整数部分ACALL WC51DDRMOVA,39H;第2行第10列显示小数点ACALL WC51DDRMOVA,3AH;第2行第11列显示小数点后1位ACALL WC51DDRMOVA,3BH;第2行第12列显示小数点后2位ACALL WC51DDRAJMP LOOP;初始化子程序INIT: MOV A,#00000001H;清屏ACALL WC51RMOV A,#00111000B ;使用8位数据,显示两行,使用5×7的字型LCALL WC51RMOV A,#00001100B ;显示器开,光标关,字符不闪烁LCALL WC51RMOV A,#00000110B ;字符不动,光标自动右移一格LCALL WC51RRET;检查忙子程序F_BUSY:PUSH ACC ;保护现场MOV P0,#0FFHCLR RSSETB RWWAIT:CLR ESETB EJB P0.7,WAIT;忙,等待POP ACC ;不忙,恢复现场RET;写入命令子程序WC51R:ACALL F_BUSYCLR ECLR RSCLR RWSETB EMOV P0,ACCCLR ERET;写入数据子程序WC51DDR:ACALL F_BUSYCLR ESETB RSCLR RWSETB EMOV P0,ACCCLR ERET;*;A/D转换子程序,8个通道转换一次转换结果依次存入30H37H;*TEST:MOVR0,#30HMOVR2,#00HTESTART:MOVP2,#0FFHMOVA,R2MOVP3,ACLRSTNOPNOPSETBSTNOPNOPCLRSTNOPNOPWAIT1:JNBEOC,WAIT1MOVD:SETBOENOPNOPMOVA,P2MOVR0,ACLROENOPNOPINCR0INC R2CJNER2,#8,TESTARTRET;*;延时子程序;*DL10MS:MOVR6,#0D0H ;延时10MS子程序DL1:MOVR7,#10HDL2:DJNZR7,DL2DJNZR6,DL1RETEND4C语言源程序清单#include <reg51.h>#include <absacc.h> /定义绝对地址访问#include <intrins.h> #define uchar unsigned char#define uint unsigned intsbit RS=P17;/定义LCD1602端口线sbit RW=P16;sbit EN=P15;sbit ST=P37;/定义0808控制线sbit OE=P36;sbit EOC=P13;sbit CLK=P14;sbit key1=P10;/通道选择按键uchar data chnumber;/存放当前通道号uchar disbuffer4=0,'.',0,0; /定义显示缓冲区uchar data ad_data8=0,0,0,0,0,0,0,0;/0808的8个通道转换数据缓冲区uint temp;/检查忙函数void fbusy()P0 = 0xff;RS = 0;RW = 1;EN = 1;EN = 0;while(P0 & 0x80)EN = 0;EN = 1;/写命令函数void wc51r(uchar j) fbusy();EN = 0;RS = 0;RW = 0;EN = 1;P0 = j;EN = 0;/写数据函数void wc51ddr(uchar j) fbusy();/读状态;EN = 0;RS = 1;RW = 0;EN = 1;P0 = j;EN = 0;void init()wc51r(0x01); /清屏wc51r(0x38); /使用8位数据,显示两行,使用5*7的字型wc51r(0x0c); /显示器开,光标开,字符不闪烁wc51r(0x06); /字符不动,光标自动右移一格/*0808转换子函数*/test()uchar m; for (m=0;m<8;m+)P3=m;/送通道地址ST=0;_nop_();_nop_();ST=1;_nop_();_nop_();ST=0;/锁存通道地址启动转换_nop_();_nop_();_nop_();_nop_();while (EOC=0);/等待转换结束OE=1;ad_datam=P2;OE=0;/读取当前通道转换数据/*延时函数*void delay(uint i) /延时函数uint y,j;for (j=0;j<i;j+)for (y=0;y<0xff;y+);/定时器/计数器T0产生0808的时钟void T0X(void)interrupt 1 using 0 CLK=CLK; void main(void)uchar i;SP=0X50;TMOD=0x02;TH0=246;TL0=246;ET0=1;EA=1;TR0=1;delay(10);init();wc51r(0x81); /写入显示缓冲区起始地址为第1行第1列wc51ddr('A'); /第1行第1列显示字母Awc51ddr('D'); /第1行第2列显示字母Dwc51ddr('D'); /第1行第3列显示字母 Dwc51ddr('R'); /第1行第4列显示字母 Rwc51ddr(':'); /第1行第4列显示字母 :wc51r(0xC0); /写入显示缓冲区起始地址为第2行第1列wc51ddr('V'); /第2行第1列显示字母Vwc51ddr('A'); /第2行第2列显示字母Awc51ddr('L'); /第2行第3列显示字母 Lwc51ddr('U'); /第2行第4列显示字母 Uwc51ddr('E'); /第2行第5列显示字母 Ewc51ddr(':'); /第2行第6列显示字母 :while(1) test();/调用ADC0808转换程序8个通道转换一次if (key1=0) while(key1=0); chnumber+;if (chnumber=8)chnumber=0;/有键按下,当前通道地址加1temp=ad_datachnumber;/取出当前通道值,转换成电压值所对应的字符temp=(temp*100)/51;disbuffer0=temp/100+0x30;temp=temp%100;disbuffer2=temp/10+0x30;disbuffer3=temp%10+0x30;wc51r(0x88); wc51ddr(chnumber+0x30); wc51r(0xc8); /显示当前通道 for (i=0;i<4;i+) wc51ddr(disbufferi); -第 9 页-