您的当前位置:首页多路数字电压表的设计

多路数字电压表的设计

来源:小侦探旅游网


8.3 多路数字电压表的设计

数字电压表是电子测量中经常用到的电子器件,传统的指针式电压表功能单一、精度低、不能满足数字时代的要求。而采用单片机的数字电压表精度高、抗干扰能力强、可扩展性强、使用方便,在日常生活中广泛应用。

8.3.1 多路数字电压表的功能要求

多路数字电压表的功能要求如下: (1) 输入电压为8路。

(2) 电压值的范畴为0~5V。

(3) 测量的最小分辨率为0.019V,测量误差为0.02V。。

(4) 能通过显示器显示通道和通道电压,有效位数为小数点后两位

8.3.2 多路数字电压表的总体设计

多路数字电压表的总体结构如图8.9所示,处理过程如下:先用A/D转换器对各路电压值进行采样,得到相应的数字量,再按数字量与模拟量成正比关系运算得到对应的模拟电压值,然后把模拟值通过显示器显示出来,另外可以通过按键选择通道。

51单片机 ADC0808 复位电路 按键 LCD 时钟电路

图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所示。

RESPACK-8RP1LM016LLCD11VSSVDDVEEC11nFRSRWEP174P165P156CRYSTAL23456789P00P01P02P03P04P05P06P07123X1C21nFU119XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD39383736353433322122232425262728P00P01P02P03P04P05P06P07P20P21P22P23P24P25P26P2718XTAL2C391nFRSTU29OEVREF(-)VREF(+)ALEADD CADD BADD AIN7IN6IN5IN4IN3IN2IN1IN0161222ST23ADDC24ADDB25ADDA54321282726R4200293031PSENALEEA1714158181920217610OUT8OUT7OUT6OUT5OUT4OUT3OUT2OUT1EOCSTARTCLOCKADC0808P007P018P029P0310P0411P0512P0613P0714D0D1D2D3D4D5D6D7RV156%1kR110kP15P16P1712345678P1.0/T2P1.1/T2EXP1.2P1.3P1.4P1.5P1.6P1.7AT89C5210ADDA11ADDB12ADDC13141516ST1750%1kRV2 图8.10 多路数字电压表的电路原理图

其中,ADC0808(0809) 的数据线D0~D7与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控制,每10s取反一次,则CLOCK的时钟周期为20s,频率为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/W与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,当前通道值转换成电压值,显示当前通道。

2.A/D转换子程序

A/D转换子程序用于对ADC0808的8路输入模拟电压进行一次A/D转换,并将转换的数值存入8个相应的存储单元中,流程图如图8.12所示。A/D转换子程序每隔一定时间调用一次,即隔一段时间对输入电压采样一次。

开始 定时/计数器初始化 LCD初始化 开始 LCD显示提示信息 启动一次转换 调用A/D转换子程序 A/D转换结束EOC=1? 否 判通道键是否按是 下,按下加1 取数据(OE=1) 当前通道数字量0808通道地址加1 转换成电压 是 地址数小于8 显示当前通道值 否

返回 图8.11 主程序流程 图8.12 A/D转换子程序流程

3.汇编语言源程序清单

;30H~37H存放转换的数字量

;38H~3BH分别放电压当前通道电压的个位、小数点后1位、小数点后2位 ;3CH单片为通道计数器 RS BIT P1.7 ;定义LCD1602端口线 RW BIT P1.6 E BIT P1.5 ST BIT P3.7 ;定义0808控制线 OE BIT P3.6 EOC BIT P1.3 CLK BIT P1.4 KEY1 BIT P1.0 ;通道选择按键 ORG 0000H LJMP MAIN ORG 000BH CPL CLK ; 定时/计数器0中断,产生转换时钟 RETI

ORG 50H

3

;主程序

MAIN: MOV SP,#50H MOV 39H,#'.' MOV TMOD,#02H MOV TH0,#246 MOV TL0,#246 SETB ET0 SETB EA SETB TR0 LCALL DL10MS ACALL INIT MOV A,#81H ACALL WC51R MOV A,#'A' ACALL WC51DDR MOV A,#'D' ACALL WC51DDR MOV A,#'D' ACALL WC51DDR MOV A,#'R' ACALL WC51DDR MOV A,#':' ACALL WC51DDR MOV A,#0C0H ACALL WC51R MOV A,#'V' ACALL WC51DDR MOV A,#'A' ACALL WC51DDR MOV A,#'L' ACALL WC51DDR MOV A,#'U' ACALL WC51DDR MOV A,#'E' ACALL WC51DDR MOV A,#':' ACALL WC51DDR LOOP: LCALL TEST JB KEY1,NEXT WAIT2: JNB KEY1,WAIT2 INC 3CH MOV A,3CH CJNE A,#08,NEXT MOV 3CH,#00

NEXT: MOV A,#30H ADD A,3CH MOV R0,A MOV A,@R0 MOV B,#51 DIV AB ADD A,#30H ;写入显示缓冲区起始地址为第1行第1列 ;第1行第2列显示字母'H' ;第1行第3列显示字母\"O\" ;第1行第4列显示字母'W' ;第1行第5列显示字母'U'

;第2行第6列显示字母'!'

;写入显示缓冲区起始地址为第2行第5列 ;第2行第5列显示字母'A' ;第2行第6列显示字母'R' ;第2行第7列显示字母'E' ;第2行第8列显示字母' ' ;第2行第9列显示字母'Y'

;第2行第10列显示字母'O'

;调用ADC0808转换程序8个通道转换一次

;有键按下,当前通道地址加1

;取出当前通道值,转换成电压值所对应的字符

MOV 38H,A MOV A,B CLR F0 SUBB A,#1AH MOV F0,C MOV A,#10 MUL AB MOV B,#51 DIV AB JB F0,LOOP2 ADD A,#5

LOOP2: ADD A,#30H MOV 3AH,A MOV A,B CLR F0 SUBB A,#1AH MOV F0,C MOV A,#10 MUL AB MOV B,#51 DIV AB JB F0,LOOP3 ADD A,#5

LOOP3: ADD A,#30H MOV 3BH,A MOV A,#88H ;写入显示缓冲区起始地址为第1行第9列 ACALL WC51R MOV A,3CH ADD A,#30H ;第1行第9列显示通道号 ACALL WC51DDR MOV A,#0C8H ;写入显示缓冲区起始地址为第2行第9列 ACALL WC51R MOV A,38H ;第2行第9列显示整数部分 ACALL WC51DDR MOV A,39H ;第2行第10列显示小数点 ACALL WC51DDR MOV A,3AH ;第2行第11列显示小数点后1位 ACALL WC51DDR MOV A,3BH ;第2行第12列显示小数点后2位 ACALL WC51DDR AJMP LOOP ;初始化子程序

INIT: MOV A,#00000001H ;清屏 ACALL WC51R MOV A,#00111000B ;使用8位数据,显示两行,使用5×7的字型 LCALL WC51R MOV A,#00001100B ;显示器开,光标关,字符不闪烁 LCALL WC51R MOV A,#00000110B ;字符不动,光标自动右移一格 LCALL WC51R RET 5

;检查忙子程序

F_BUSY:PUSH ACC ;保护现场 MOV P0,#0FFH CLR RS SETB RW WAIT: CLR E SETB E JB P0.7,WAIT ;忙,等待 POP ACC ;不忙,恢复现场 RET ;写入命令子程序

WC51R: ACALL F_BUSY CLR E CLR RS CLR RW SETB E MOV P0,ACC CLR E RET ;写入数据子程序

WC51DDR:ACALL F_BUSY CLR E SETB RS CLR RW SETB E MOV P0,ACC CLR E RET

;***************************************************** ;A/D转换子程序,8个通道转换一次转换结果依次存入30H~37H

;***************************************************** TEST: MOV R0,#30H MOV R2,#00H TESTART:MOV P2,#0FFH MOV A,R2 MOV P3,A CLR ST NOP NOP SETB ST NOP NOP CLR ST NOP NOP

WAIT1: JNB EOC,WAIT1 MOVD: SETB OE NOP NOP MOV A,P2 MOV @R0,A

CLR OE NOP NOP INC R0 INC R2 CJNE R2,#8,TESTART RET

;************************************* ;延时子程序

;*************************************

DL10MS: MOV R6,#0D0H ;延时10MS子程序 DL1: MOV R7,#10H DL2: DJNZ R7,DL2 DJNZ R6,DL1 RET END

4.C语言源程序清单

#include

#include //定义绝对地址访问 #include

#define uchar unsigned char #define uint unsigned int sbit RS=P1^7; //定义LCD1602端口线 sbit RW=P1^6; sbit EN=P1^5; sbit ST=P3^7; //定义0808控制线 sbit OE=P3^6; sbit EOC=P1^3; sbit CLK=P1^4; sbit key1=P1^0; //通道选择按键 uchar data chnumber; //存放当前通道号 uchar disbuffer[4]={0,'.',0,0}; //定义显示缓冲区

uchar data ad_data[8]={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; } }

//写命令函数 7

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_data[m]=P2;OE=0; //读取当前通道转换数据 } }

//************延时函数************ void delay(uint i) //延时函数 {uint y,j;

for (j=0;jfor (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列显示字母A wc51ddr('D'); //第1行第2列显示字母D wc51ddr('D'); //第1行第3列显示字母 D wc51ddr('R'); //第1行第4列显示字母 R wc51ddr(':'); //第1行第4列显示字母 :

wc51r(0xC0); //写入显示缓冲区起始地址为第2行第1列 wc51ddr('V'); //第2行第1列显示字母V wc51ddr('A'); //第2行第2列显示字母A wc51ddr('L'); //第2行第3列显示字母 L wc51ddr('U'); //第2行第4列显示字母 U wc51ddr('E'); //第2行第5列显示字母 E wc51ddr(':'); //第2行第6列显示字母 : while(1) {

test(); //调用ADC0808转换程序8个通道转换一次

if (key1==0) {while(key1==0); chnumber++;if (chnumber==8)chnumber=0;}

//有键按下,当前通道地址加1 temp=ad_data[chnumber]; //取出当前通道值,转换成电压值所对应的字符 temp=(temp*100)/51; disbuffer[0]=temp/100+0x30; temp=temp%100; disbuffer[2]=temp/10+0x30; disbuffer[3]=temp%10+0x30; wc51r(0x88); wc51ddr(chnumber+0x30); wc51r(0xc8); //显示当前通道 for (i=0;i<4;i++) wc51ddr(disbuffer[i]); } }

9

因篇幅问题不能全部显示,请点此查看更多更全内容