多路数字电压表的设计

多路数字电压表的设计
多路数字电压表的设计

8.3 多路数字电压表的设计

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

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

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

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

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

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

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

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

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

51单片机

时钟电路

复位电路

LCD 按键

ADC0808

P 17P 16P 15P17

P16P15P07P 07P06P05P04P03P02P01P00P 00P 01P 02P 03P 04P 05P 06P 07

P 00P 01P 02P 03P 04P 05P 06P27

ST P23P26P21P22P20P24P25ADDC ADDB ADDA ADDA ADDB ADDC ST XTAL2

18

XTAL1

19

ALE 30EA

31

PSEN 29RST

9

P0.0/AD039P0.1/AD138P0.2/AD237P0.3/AD336P0.4/AD435P0.5/AD534P0.6/AD633P0.7/AD732P1.0/T21P1.1/T2EX 2P1.23P1.34P1.45P1.56P1.67P1.78

P3.0/RXD 10P3.1/TXD 11P3.2/INT012P3.3/INT113P3.4/T014P3.7/RD

17

P3.6/WR 16

P3.5/T115P2.7/A1528

P2.0/A821P2.1/A922P2.2/A1023P2.3/A1124P2.4/A1225P2.5/A1326P2.6/A1427U1

AT89C52

D 7

14

D 613D 512D 411D 310D 29D 18D 0

7E 6

R W 5R S 4V S S 1V D D 2V E E

3

LCD1

LM016L

R1

10k

234567891

RP1

RESPACK-8

OUT121ADD B 24ADD A

25ADD C 23VREF(+)12VREF(-)16IN31IN42IN53IN64IN75START 6OUT58EOC 7OE

9

CLOCK 10

OUT220OUT714OUT615OUT817OUT418OUT319IN228IN127IN0

26

ALE 22U2

ADC0808

X1

CRYSTAL

C1

1nF

C2

1nF

C3

1nF

R4

200

56%

RV1

1k

50%

RV2

1k

图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控制,每10s 取反一次,则CLOCK 的时钟周期为20s ,频率为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转换子程序每隔一定时间调用一次,即隔一段时间对输入电压采样一次。

图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 M AIN

ORG 000BH

CPL CLK ; 定时/计数器0中断,产生转换时钟

RETI

ORG 50H

;主程序

.

MAIN: MOV SP,#50H

MOV 39H,#'.'

MOV T MOD,#02H

MOV T H0,#246

MOV T L0,#246

SETB ET0

SETB EA

SETB TR0

LCALL DL10MS

ACALL INIT

MOV A,#81H ;写入显示缓冲区起始地址为第1行第1列

ACALL WC51R

MOV A,#'A' ;第1行第2列显示字母'H'

ACALL WC51DDR

MOV A,#'D' ;第1行第3列显示字母"O"

ACALL WC51DDR

MOV A,#'D' ;第1行第4列显示字母'W'

ACALL WC51DDR

MOV A,#'R' ;第1行第5列显示字母'U'

ACALL WC51DDR

MOV A,#':' ;第2行第6列显示字母'!'

ACALL WC51DDR

MOV A,#0C0H ;写入显示缓冲区起始地址为第2行第5列

ACALL WC51R

MOV A,#'V' ;第2行第5列显示字母'A'

ACALL WC51DDR

MOV A,#'A' ;第2行第6列显示字母'R'

ACALL WC51DDR

MOV A,#'L' ;第2行第7列显示字母'E'

ACALL WC51DDR

MOV A,#'U' ;第2行第8列显示字母' '

ACALL WC51DDR

MOV A,#'E' ;第2行第9列显示字母'Y'

ACALL WC51DDR

MOV A,#':' ;第2行第10列显示字母'O'

ACALL WC51DDR

LOOP: LCALL TEST ;调用ADC0808转换程序8个通道转换一次JB KEY1,NEXT ;有键按下,当前通道地址加1

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

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

;检查忙子程序

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;

}

}

//写命令函数

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;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列显示字母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]);

}

}

如有侵权请联系告知删除,感谢你们的配合!

如有侵权请联系告知删除,感谢你们的配合!

相关主题
相关文档
最新文档