基于单片机的电压表设计.docx
《基于单片机的电压表设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的电压表设计.docx(18页珍藏版)》请在冰豆网上搜索。
基于单片机的电压表设计
基于单片机的电压表设计
1引言
随着微电子技术的不断发展,微处理器芯片的集成程度越来越高,单片机已可以在一块芯片上同时集成CPU、存储器、定时器/计数电路,这就很容易将计算机技术与测量控制技术结合,组成智能化测量控制系统。
数字电压表(DigitalVoltmeter)简称DVM,它是采用数字化测量技术,把连续的模拟量(直流输入电压)转换成不连续、离散的数字形式并加以显示的仪表。
与此同时,由DVM扩展而成的各种通用及专用数字仪器仪表,也把电量及非电量测量技术提高到崭新水平。
本设计重点介绍单片机、A/D转换器以及由它们构成的数字电压表的工作原理。
目前,由各种单片机、A/D转换器构成的数字电压表,已被广泛用于电子及电工测量、工业自动化仪表、自动测试系统等智能化测量领域,示出强大的生命力理。
2设计原理及要求
本设计是利用单片机AT89C51、ADC0804以及74HC573设计一个数字电压表,可以测量0-5V、0-50V之间的直流电压值,并且用四位数码管显示。
2.1数字电压表的实现原理
该设计主要由三个模块组成:
A/D转换模块,数据处理模块及显示模块。
A/D转换主要由芯片ADC0804来完成,它负责把采集到的模拟量转换为相应的数字量在传送到数据处理模块。
数据处理则由芯片AT89C51来完成,其负责把ADC0804传送来的数字量经过一定的数据处理,产生相应的显示码送到显示模块进行显示;此外,它还控制着74HC373芯片工作。
2.2数字电压表的设计指标
(1)以AT89C51单片机为核心器件,组成一个简单的直流数字电压表。
(2)采用1路模拟量输入,能够测量0-5V之间的直流电压值。
(3)在测量0-5V的基础上,换档实现0-50V的测量。
(4)电压显示用4位一体的LED数码管显示,至少能够显示两位小数。
(5)PCB制板,电路整洁大方。
(6)尽量使用较少的元器件。
3软件仿真电路设计
3.1设计思路
(1)根据设计指标,选择AT89C51单片机为核心控制器件。
(2)A/D转换采用ADC0804实现,与单片机的接口为P1口和P3口的高三位引脚。
(3)电压显示采用4位一体的LED数码管。
(4)LED数码的段码输入,由并行端口P0产生,并经过74HC573锁存后,连接到数码管的ABCDEFGDP管脚;LED数码的位码输入,由并行端口P2产生,并经过74HC573锁存后,连接到数码管的12
3.2硬件电路设计图
硬件电路设计由5个部分组成:
A/D转换电路,AT89C51单片机系统,LED显示系统、时钟电路以及测量电压输入电路。
硬件电路设计框图如图1所示。
图1数字电压表系统硬件设计框图
3.3AT89C51的功能介绍
3.3.1简单概述
AT89C51是一种带4K字节闪存可编程可擦除只读存储器的低电压、高性能CMOS8位微处理器,俗称单片机。
AT89C51是一种带2K字节闪存可编程可擦除只读存储器的单片机。
AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
外形及引脚排列如图3-2所示。
3.3.2主要功能特性
(1)4K字节可编程闪烁存储器。
(2)32个双向I/O口;128×8位内部RAM。
(3)2个16位可编程定时/计数器中断,时钟频率0-24MHz。
(4)可编程串行通道。
(5)5个中断源。
(6)2个读写中断口线。
(7)低功耗的闲置和掉电模式。
(8)片内振荡器和时钟电路。
图3-2
3.3.3AT89C51的引脚介绍
89C51单片机多采用40只引脚的双列直插封装(DIP)方式,下面分别简单介绍。
(1)电源引脚
电源引脚接入单片机的工作电源。
Vcc(40引脚):
+5V电源。
GND(20引脚):
接地。
(2)时钟引脚
XTAL1(19引脚):
片内振荡器反相放大器和时钟发生器电路的输入端。
XTAL2(20引脚):
片内振荡器反相放大器的输出端。
图3-3电源接入方式
(3)复位RST(9引脚)
在振荡器运行时,有两个机器周期(24个振荡周期)以上的高电平出现在此引脚时,将使单片机复位,只要这个脚保持高电平,51芯片便循环复位。
(4)
/Vpp(31引脚)
为外部程序存储器访问允许控制端。
当它为高电平时,单片机读片内程序存储器,在PC值超过0FFFH后将自动转向外部程序存储器。
当它为低电平时,只限定在外部程序存储器,地址为0000H~FFFFH。
Vpp为该引脚的第二功能,为编程电压输入端。
(5)ALE/
(30引脚)
ALE为低八位地址锁存允许信号。
在系统扩展时,ALE的负跳沿江P0口发出的第八位地址锁存在外接的地址锁存器,然后再作为数据端口。
为该引脚的第二功能,在对片外存储器编程时,此引脚为编程脉冲输入端。
(6)
(29引脚)
片外程序存储器的读选通信号。
在单片机读片外程序存储器时,此引脚输出脉冲的负跳沿作为读片外程序存储器的选通信号。
(7)pin39-pin32为P0.0-P0.7输入输出脚,称为P0口。
P0是一个8位漏极开路型双向I/O口。
内部不带上拉电阻,当外接上拉电阻时,P0口能以吸收电流的方式驱动八个LSTTL负载电路。
通常在使用时外接上拉电阻,用来驱动多个数码管。
在访问外部程序和外部数据存储器时,P0口是分时转换的地址(低8位)/数据总线,不需要外接上拉电阻。
(8)Pin1-Pin8为P1.0-P1.7输入输出脚,称为P1口,是一个带内部上拉电阻的8位双向I/0口。
P1口能驱动4个LSTTL负载。
(9)Pin21-Pin28为P2.0-P2.7输入输出脚,称为P2口。
P2口是一个带内部上拉电阻的8位双向I/O口,P2口能驱动4个LSTTL负载。
端口置1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部Flash程序存储器编程时,接收高8位地址和控制信息。
在访问外部程序和16位外部数据存储器时,P2口送出高8位地址。
而在访问8位地址的外部数据存储器时其引脚上的内容在此期间不会改变。
(10)Pin10-Pin17为P3.0-P3.7输入输出脚,称为P3口。
P3口是一个带内部上拉电阻的8位双向I/O口,P2口能驱动4个LSTTL负载,这8个引脚还用于专门的第二功能。
端口置1时,内部上拉电阻将端口拉到高电平,作输入用。
对内部Flash程序存储器编程时,接控制信息。
3.4ADC0804的引脚及功能介绍
3.4.1芯片概述
ADC0804是一个8位CMOS型逐次比较式A/D转换器,具有三态锁存输出功能,最短转换时间为100us。
芯片模型如图3-4所示。
图3-4ADC0804芯片模型
3.4.2引脚简介
/CS:
芯片片选信号,低电平有效,即/CS=0,该芯片才能正常工作,在外接多个ADC0804芯片时,该信号可以作为选择地址使用,通过不同的地址信号使能不同的ADC0804芯片,从而可以实现多个ADC通道的分时复用。
/WR:
启动ADC0804进行ADC采样,该信号低电平有效,即/WR信号由高电平变成低电平时,触发一次ADC转换。
/RD:
低电平有效,即/RD=0时,可以通过数据端口DB0~DB7读出本次的采样结果。
UIN(+)和UIN(-):
模拟电压输入端,模拟电压输入接UIN(+)端,UIN(-)端接地。
双边输入时UIN(+)、UIN(-)分别接模拟电压信号的正端和负端。
当输入的模拟电压信号存在“零点漂移电压”时,可在UIN(-)接一等值的零点补偿电压,变换时将自动从UIN(+)中减去这一电压。
VREF/2:
参考电压接入引脚,该引脚可外接电压也可悬空,若外界电压,则ADC的参考电压为该外界电压的两倍,如不外接,则Vref与Vcc共用电源电压,此时ADC的参考电压即为电源电压Vcc的值。
CLKR和CLKIN:
外接RC电路产生模数转换器所需的时钟信号,时钟频率CLK=1/1.1RC,一般要求频率范围100KHz~1.28MHz。
AGND和DGND:
分别接模拟地和数字地。
/INT:
中断请求信号输出引脚,该引脚低电平有效,当一次A/D转换完成后,
将引起/INT=0,实际应用时,该引脚应与微处理器的外部中断输入引脚相连(如51单片机的INT0,INT1脚),当产生/INT信号有效时,还需等待/RD=0才能正确读出A/D转换结果,若ADC0804单独使用,则可以将/INT引脚悬空。
DB0~DB7:
输出A/D转换后的8位二进制结果。
3.4.3ADC0804的转换原理
ADC0804采用逐次比较的方法完成A/D转换,由单一的+5V电源供电。
ADC0804完成一次转换需100μs左右,它具有输出TTL三态锁存缓冲器,可直接连接到AT89C51的数据总线上。
通过适当的外接电路,ADC0804可对0~5V的模拟信号进行转换。
3.574HC373芯片的引脚及功能
3.5.1芯片概述
74LS373是一种带有三态门的8D锁存器,其在本设计中是锁存P0口的低8位地址,芯片模型如图3-5所示。
图3-5
3.5.2引脚介绍
(1)D0~D7:
8位数据输入线;
(2)Q0~Q7:
8位数据输出线
(3)LE:
数据输入锁存选通信号。
当加到该引脚的信号为高电平时,外部数据选通到内部锁存器,负跳变时,数据锁存到锁存器中。
(4)
:
数据输出允许信号,低电平有效。
当该信号为低电平时,三态门打开,锁存器中的数据输出到数据输出线上,当该信号为高电平时,输出线为高阻态。
3.6LED数码管的控制显示
LED显示器由若干个发光二极管组成,当发光二极管导通时,相应的一个笔画或一个点就发光。
控制相应的管导通,就能显示出对应字符。
各段LED显示器需要由驱动电路驱动。
在七段LED显示器中,通常将各段发光二极管的阴极或阳极连在一起作为公共端。
将各段发光二极管连在一起的叫共阳极显示器,用低电平驱动;将阴极连在一起的叫共阴极显示器,用高电平驱动。
静态显示就是每一个显示器各笔画段都要独占具有一个锁存功能的输出口线,CPU把要显示的字形代码送到输出口上,就可以使显示器上显示所需的数字或符号,此后,即使CPU不在去访问它,因为各笔画段借口具有锁存功能,显示的内容也不会消失。
动态显示是指显示器显示某一字符时,相应段的发光二极管恒定地导通或截止。
静态显示有并行输出和串行输出两种方式。
在本系统中数码管使用共阴极接法而且是用动态显示。
LED数码管模型如图3-6所示。
图3-6
4系统软件程序的设计
#include//头文件包含特殊功能寄存器的定义
#defineucharunsignedchar
#defineuintunsignedint
#defineDataPort1P0//定义数据端口程序中遇到DataPort1则用P0替换
#defineDataPort2P2//定义数据端口程序中遇到DataPort2则用P2替换
/*--------------定义AT89C51的管脚信号-----------------------------*/
sbitLATCH1=P2^4;//定义锁存使能端口段锁存
sbitLATCH2=P2^5;//定义锁存使能端口位锁存
sbitcs=P3^5;//即定义cs为P3口的第5位,以便进行位操作
sbitrd=P3^7;//即定义rd为P3口的第6位,以便进行位操作
sbitwr=P3^6;//即定义wr为P3口的第7位,以便进行位操作
sbitINTR=P3^2;//即定义中断请求INTR为P3口的第2位,以便进行位操作
sbitchose=P3^0;//即定义chose为P3口的第0位,以便进行位操作
/*-----------------------定义无符号整形变量-----------------------*/
uinttemp,D1,D2,D3,D4;//uint是无符号整数,表示范围是0到65535
uintshu,AD_read();
/*---------------------定义无符号字符变量--------------------------*/
unsignedcharcodedofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//段码3f对应0,依次有段码71对应F
unsignedcharcodedofly_DuanMadian[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1};
unsignedcharcodedofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//0xfe使得数码管1点亮,0xfd使得数码管2点亮,依次使得相应的数码管点亮,即位码
/*----------------------函数声明----------------------------------*/
voiddelaying(uintz);
voidDelay(unsignedintt);
voidAD_init();
voidAD_start();
voiddisplay1(ucharqian,ucharbai,ucharshi,ucharge);
voiddisplay2(ucharqian,ucharbai,ucharshi,ucharge);
/*---------------------------主函数-------------------------------*/
main()
{
AD_init();
while
(1)
{
AD_start();
while(INTR==1);//AD转换是否结束,结束为低电平
INTR=0;
shu=AD_read();//cpu读入的AD转换之后的数字量给shu
shu=shu*196.07;//255*196.07=49997.85
D1=shu/10000;//对应第一个数码管段码
shu=shu%10000;
D2=shu/1000;//对应第二个数码管段码
shu=shu%1000;
D3=shu/100;//对应第三个数码管的段码
shu=shu%100;
D4=shu/10;//对应第三个数码管的段码
if(chose==1)display1(D1,D2,D3,D4);
elsedisplay2(D1,D2,D3,D4);
}
}
/*每次A/D转换结束,都向CPU请求中断,CPU响应中断,执行中断服务程序,读取A/D的结果*/
/*-----------------------------------------------------------------*/
voidDelay(unsignedintt)//延时函数,t是无符号整数
{
while(--t);
}
/*-----------------------------------------------------------------*/
voiddelaying(uintz)//延时函数,z是无符号整数
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*-----------------------------------------------------------------*/
voidAD_init()//AD初始化函数,cpu不写也不读
{
cs=1;
wr=1;
rd=1;
}
/*-----------------------------------------------------------------*/voidAD_start()//启动AD转换,!
wr是cpu写入外部数据存储器选通信号,cpu写完后通过wr=1,cs=1关闭,不再写入
{P1=0xff;//0x表示十六进制
cs=0;//cpu写入,启动AD转换
wr=0;
}
/*-----------------------------------------------------------------*/
uintAD_read()//!
rd是cpu读外部数据存储器选通信号,cpu读入AD转换之后的数字量,读完之后通过rd=1,cs=1关闭,不再读入
{
cs=0;
rd=0;
delaying
(1);//调用延时
temp=P1;
rd=1;
cs=1;
return(temp);
}
/*-----------------------------------------------------------------*/
voiddisplay1(ucharqian,ucharbai,ucharshi,ucharge)
{
DataPort2=dofly_WeiMa[0];//取位码,使第一个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMa[qian];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
DataPort2=dofly_WeiMa[1];//取位码,使第二个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMadian[bai];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
DataPort2=dofly_WeiMa[2];//取位码,使第三个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMa[shi];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
DataPort2=dofly_WeiMa[3];//取位码,使第四个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMa[ge];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
}
/*-----------------------------------------------------------------*/
voiddisplay2(ucharqian,ucharbai,ucharshi,ucharge)
{
DataPort2=dofly_WeiMa[0];//取位码,使第一个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_[qian];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
DataPort2=dofly_WeiMa[1];//取位码,使第二个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMa[bai];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
DataPort2=dofly_WeiMa[2];//取位码,使第三个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMa[shi];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
DataPort2=dofly_WeiMa[3];//取位码,使第四个数码管亮
LATCH2=1;//位锁存
LATCH2=0;
DataPort1=dofly_DuanMa[ge];//取显示数据,段码
LATCH1=1;//段锁存
LATCH1=0;
Delay(200);//扫描间隙延时,时间太长会闪烁,太短会造成重影
}
5测试及性能分析
5.1测试
本设计应用Proteus7及KeiluVision4软件,首先根据自己设计的电路图用Proteus7软件画出电路模型,关于这个软件的使用通过查一些资料和自己的摸索学习;然后我们用KeiluVision4软件对所编写的程序进行编译、链接,如果没有错误和警告便可生成程序的hex文件,将此文件加到电路图上使软硬件结合运行,最后进行端口的对比测试。
我定义了AT89C51的P3^0口为chose;当chose=1时,测量0-50V的直流电压;当chose=0时,测量0-5V的直流电压;在测试的过程中,我们发现测得的值会有些误差。
误差原因主要有:
我采用焊板去做,实际元件的值与理论元件值总是有差距的;我采用了8位A/D转换器,具有一定的理论误差精度;测量仪器的读数本身也具有一定的误差。
5.2性能分析
由于ADC0804为8位A/D转换器,当输入电压为5.00V时,输出数据值为255(FFH),因此单片机最大的数值分辨率为0.0196V(即5/255),这就决定了该电压表的最大分辨率(精度)只能达到0.0196V;当输入电压为50.00V时,输出数据值为255(FFH)因此单片机最大的数值分辨率为0.196V(即50/255)。
这就决定了该电压表的最大分辨率(精度)只能达到0.196V;;如要获得更高的精度要求,应采用12位、13位或者是16位的A/D转换器。
6设计总结
通过这次设计学会了Proteus、Keil以及AltiumDesigner6软件的使用方法,掌握了从系统的需要、方案的设计、功能模块的划分、原理图的设计和电路图的仿真的设计流程,积累了不少经验。
基于单片机的数字电压电流表使用性强、结构简单、成本低、外接元件少。
在实际应用工作应能好,测量准确,精度高。
此数字电压表可以测量0-5V的1路模拟直流输入电压值,并通过一个四位一体的7段数码管显示出来;同时通过转换开关可以检测1路模拟直流输入0-50V电压值,并通过一个四位一体的7段数码管显示出来。
通过本次设计,我对单片机这门课有了进一步的了解。
无论是在硬件连接方面还是在软件编程方面。
本次设计采用了AT89C51单片机芯片,与以往的单片机相比增加了许多新的功能,使其功能更为完善,应用