1、 目 录1. 引言.12. 设计的总体方案.2 2.1 设计要求.2 2.2 设计思路.2 2.3 设计方案.23. 硬件设计方案.3 3.1 A/D转换模块.3 3.1.1 逐次逼近型A/D转化器原理.3 3.1.2 PCF8591主要特性.3 3.1.3 PCF8591的外部引脚特性.4 3.1.4 PCF8591的内部结构及工作流程.53.2 单片机系统.7 3.2.1 STC90C51性能.7 3.2.2 STC90C51各引脚功能.7 3.3 复位电路和时钟电路.9 3.3.1 复位电路的设计.9 3.3.2 时钟电路的设计.93.4 LED显示电路的设计.10 3.4.1 LED基
2、本结构.10 3.4.2 LED显示器的选择.113.4.3 LED译码方式.113.4.4 LED显示器与单片机接口技术.12 3.5 总体电路的设计.134. 程序设计.154.1 程序设计总方案.154.2 系统子程序设计.154.2.1 初始化程序.154.2.2 A/D转换子程序.154.2.3 显示子程序.165. 仿真.175.1 软件调试.175.2 显示结果及误差分析.175.2.1 显示结果.175.2.2 误差分析.19结论.20 参考文献.21 设计程序.22 1 引言 数字电压表(DigitalVoltmeter)简称DVM,它是采用数字化测量技术,把连续的模拟量(直
3、流输入电压)转换成不连续、离散的数字形式并加以显示的仪表。传统的指针式电压表功能单一、精度低,不能满足数字化时代的需求,采用单片机的数字电压表,由精度高、抗干扰能力强,可扩展性强、集成方便,还可与PC进行实时通信。目前,由各种单片A/D转换器构成的数字电压表,已被广泛用于电子及电工测量、工业自动化仪表、自动测试系统等智能化测量领域,示出强大的生命力。与此同时,由DVM扩展而成的各种通用及专用数字仪器仪表,也把电量及非电量测量技术提高到崭新水平。本课程设计介绍单片A/D转换器以及由它们构成的基于单片机的数字电压表的工作原理. 2 设计总体方案2.1设计要求 (1)以MCS-51系列单片机为核心器
4、件,组成一个简单的直流数字电压表。 能够测量0-20V之间的直流电压值。电压显示用4位一体的LED数码管显示,至少能够显示两位小数。尽量使用较少的元器件。2.2 设计思路根据设计要求,选择STC90C51单片机为核心控制器件。A/D转换采用PCF8591实现,与单片机的接口为P1口和P2口的高四位引脚。电压显示采用4位一体的LED数码管。LED数码的段码输入,由并行端口P0产生:位码输入,用并行端口P2低四位产生。2.3 设计方案硬件电路设计由6个部分组成; A/D转换电路,AT89C51单片机系统,LED显示系统、时钟电路、复位电路以及测量电压输入电路。硬件电路设计框图如图1所示 图1 数字
5、电压表系统硬件设计框图 3 硬件电路设计3.1 A/D转换模块 3.1.1 PCF8591描述PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行IC总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。 3.1.2 PCF8591功能 PCF8591的功能包括多路模拟输入、内置跟踪保持、8-bit模数转换和8-bit数模转
6、换。PCF8591的最大转化速率由I2C总线的最大速率决定。 3.1.3 PCF8591主要特性 1.单独供电 2.PCF8591的操作电压范围2.5V-6V 3.低待机电流 4.通过I2C总线串行输入/输出 5.PCF8591通过3个硬件地址引脚寻址 6.PCF8591的采样率由I2C总线速率决定 7.4个模拟输入可编程为单端型或差分输入 8.自动增量频道选择 9.PCF8591的模拟电压范围从VSS到VDD 10.PCF8591内置跟踪保持电路 11.8-bit逐次逼近A/D转换器 12.通过1路模拟输出实现DAC增益 3.1.4 PCF8591的外部引脚特征 PCF8591芯片有28条引
7、脚,采用双列直插式封装,其引脚图如图3所示。 图3 PCF8591引脚图下面说明各个引脚功能:AIN0AIN3:模拟信号输入端。A0A2:引脚地址端。VDD、VSS:电源端。(2.56V)SDA、SCL:I2C 总线的数据线、时钟线。OSC:外部时钟输入端,内部时钟输出端。EXT:内部、外部时钟选择线,使用内部时钟时 EXT 接地。AGND:模拟信号地。AOUT:D/A 转换输出端。VREF:基准电源端。 3.1.5 PCF8591的原理图 3.2 单片机系统 3.2.1 STC90C51性能STC90C51是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含有4KB的可反复擦写
8、的只读程序存储器和128字节的随机存储器。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容,由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,它为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。STC90C51功能性能:与MCS-51成品指令系统完全兼容;4KB可编程闪速存储器;寿命:1000次写/擦循环;数据保留时间:10年;全静态工作:0-24MHz;三级程序存储器锁定;128*8B内部RAM;32个可编程I/O口线;2个16位定时/计数器;5个中断源;可编程串行UART通道;片内震荡器和掉
9、电模式6。 3.2.2 STC90C51各引脚功能 STC90C51提供以下标准功能:4KB的Flash闪速存储器,128B内部RAM,32个I/O口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内震荡器及时钟电路,同时,STC90C51可降至0Hz静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作,掉电方式保存RAM中的内容,但震荡器停止工作并禁止其他所有工作直到下一个硬件复位。STC90C51采用PDIP封装形式,引脚配置如图5所示7。 图5 STC90C51的引脚图AT89C51
10、芯片的各引脚功能为:P0口:这组引脚共有8条,P0.0为最低位。这8个引脚有两种不同的功能,分别适用于不同的情况,第一种情况是89C51不带外存储器,P0口可以为通用I/O口使用,P0.0-P0.7用于传送CPU的输入/输出数据,这时输出数据可以得到锁存,不需要外接专用锁存器,输入数据可以得到缓冲,增加了数据输入的可靠性;第二种情况是89C51带片外存储器,P0.0-P0.7在CPU访问片外存储器时先传送片外存储器的低8位地址,然后传送CPU对片外存储器的读/写数据。P0口为开漏输出,在作为通用I/O使用时,需要在外部用电阻上拉。P1口:这8个引脚和P0口的8个引脚类似,P1.7为最高位,P1
11、.0为最低位,当P1口作为通用I/O口使用时,P1.0-P1.7的功能和P0口的第一功能相同,也用于传送用户的输入和输出数据。P2口:这组引脚的第一功能与上述两组引脚的第一功能相同即它可以作为通用I/O口使用,它的第一功能和P0口引脚的第二功能相配合,用于输出片外存储器的高8位地址,共同选中片外存储器单元,但并不是像P0口那样传送存储器的读/写数据。P3口:这组引脚的第一功能和其余三个端口的第一功能相同,第二功能为控制功能,每个引脚并不完全相同,如下表2所示: 表2 P3口各位的第二功能 Vcc为+5V电源线,Vss接地。ALE:地址锁存允许线,配合P0口的第二功能使用,在访问外部存储器时,8
12、9C51的CPU在P0.0-P0.7引脚线去传送随后而来的片外存储器读/写数据。在不访问片外存储器时,89C51自动在ALE线上输出频率为1/6震荡器频率的脉冲序列。该脉冲序列可以作为外部时钟源或定时脉冲使用。 /EA:片外存储器访问选择线,可以控制89C51使用片内ROM或使用片外ROM, 若/EA=1,则允许使用片内ROM, 若/EA=0,则只使用片外ROM。/PSEN:片外ROM的选通线,在访问片外ROM时,89C51自动在/PSEN线上产生一个负脉冲,作为片外ROM芯片的读选通信号。RST:复位线,可以使89C51处于复位(即初始化)工作状态。通常89C51复位有自动上电复位和人工按键
13、复位两种。XTAL1和XTAL2:片内震荡电路输入线,这两个端子用来外接石英晶体和微调电容,即用来连接89C51片内OSC(震荡器)的定时反馈回路。3.3 复位电路和时钟电路3.3.1 复位电路设计单片机在启动运行时都需要复位,使CPU和系统中的其他部件都处于一个确定的初始状态,并从这个状态开始工作。MCS-51单片机有一个复位引脚RST,采用施密特触发输入。当震荡器起振后,只要该引脚上出现2个机器周期以上的高电平即可确保时器件复位1。复位完成后,如果RST端继续保持高电平,MCS-51就一直处于复位状态,只要RST恢复低电平后,单片机才能进入其他工作状态。单片机的复位方式有上电自动复位和手动
14、复位两种,图6是51系列单片机统常用的上电复位和手动复位组合电路,只要Vcc上升时间不超过1ms,它们都能很好的工作1。 图6 复位电路3.3.2 时钟电路设计单片机中CPU每执行一条指令,都必须在统一的时钟脉冲的控制下严格按时间节拍进行,而这个时钟脉冲是单片机控制中的时序电路发出的。CPU执行一条指令的各个微操作所对应时间顺序称为单片机的时序。MCS-51单片机芯片内部有一个高增益反相放大器,用于构成震荡器,XTAL1为该放大器的输入端,XTAL2为该放大器输出端,但形成时钟电路还需附加其他电路1。本设计系统采用内部时钟方式,利用单片机内部的高增益反相放大器,外部电路简,只需要一个晶振和 2
15、个电容即可,如图7所示。图7 时钟电路电路中的器件选择可以通过计算和实验确定,也可以参考一些典型电路的参数,电路中,电容器C1和C2对震荡频率有微调作用,通常的取值范围是3010pF,在这个系统中选择了33pF;石英晶振选择范围最高可选24MHz,它决定了单片机电路产生的时钟信号震荡频率,在本系统中选择的是12MHz,因而时钟信号的震荡频率为12MHz。3.4 LED显示系统设计3.4.1 LED基本结构LED是发光二极管显示器的缩写。LED由于结构简单、价格便宜、与单片机接口方便等优点而得到广泛应用。LED显示器是由若干个发光二极管组成显示字段的显示器件6。在单片机中使用最多的是七段数码显示
16、器。LED七段数码显示器由8个发光二极管组成显示字段,其中7个长条形的发光二极管排列成“日”字形,另一个圆点形的发光二极管在显示器的右下角作为显示小数点用,其通过不同的组合可用来显示各种数字。LED引脚排列如下图8所示 图8 LED引脚排列3.4.2 LED显示器的选择在应用系统中,设计要求不同,使用的LED显示器的位数也不同,因此就生产了位数,尺寸,型号不同的LED显示器供选择,在本设计中,选择4位一体的数码型LED显示器,简称“4-LED”。本系统中前一位显示电压的整数位,即个位,后两位显示电压的小数位。4-LED显示器引脚如图9所示,是一个共阴极接法的4位LED数码显示管,其中a,b,c
17、,e,f,g为4位LED各段的公共输出端,1、2、3、4分别是每一位的位数选端,dp是小数点引出端,4位一体LED数码显示管的内部结构是由4个单独的LED组成,每个LED的段输出引脚在内部都并联后,引出到器件的外部。图9 4位LED引脚对于这种结构的LED显示器,它的体积和结构都符合设计要求,由于4位LED阴极的各段已经在内部连接在一起,所以必须使用动态扫描方式(将所有数码管的段选线并联在一起,用一个I/O接口控制)显示。3.4.3 LED译码方式译码方式是指由显示字符转换得到对应的字段码的方式,对于LED数码管显示器,通常的译码方式有硬件译码和软件译码方式两种。硬件译码是指利用专门的硬件电路
18、来实现显示字符码的转换。软件译码就是编写软件译码程序,通过译码程序来得到要显示的字符的字段码,译码程序通常为查表程序3。本设计系统中为了简化硬件线路设计,LED译码采用软件编程来实现。由于本设计采用的是共阴极LED,其对应的字符和字段码如下表3.3所示。 表3.3 共阴极字段码表3.4.4 LED显示器与单片机接口设计由于单片机的并行口不能直接驱动LED显示器,所以,在一般情况下,必须采用专用的驱动电路芯片,使之产生足够大的电流,显示器才能正常工作7。如果驱动电路能力差,即负载能力不够时,显示器亮度就低,而且驱动电路长期在超负荷下运行容易损坏,因此,LED显示器的驱动电路设计是一个非常重要的问
19、题。为了简化数字式直流电压表的电路设计,在LED驱动电路的设计上,可以利用单片机P0口上外接的上拉电阻来实现,即将LED的A-G段显示引脚和DP小数点显示引脚并联到P0口与上拉电阻之间,这样,就可以加大P0口作为输出口德驱动能力,使得LED能按照正常的亮度显示出数字,如图10所示。图10 LED与单片机接口间的设计3.5 总体电路设计经过以上的设计过程,可设计出基于单片机的简易数字直流电压表硬件电路原理图如图11所示。 图11 简易数字电压表电路图此电路的工作原理是:+5V模拟电压信号通过变阻器VR1分压后由PCF8591的AIN3通道进入,经过模/数转换后,产生相应的数字量经过其输出通道D0
20、-D7传送给STC90C51芯片的P1口,STC90C51负责把接收到的数字量经过数据处理,产生正确的7段数码管的显示段码传送给四位LED,同时它还通过其四位I/O口P0.0、P0.1、P0.2、P0.3产生位选信号控制数码管的亮灭。此外,AT89C51还控制PCF8591的工作。其中,单片机AT89C51通过定时器中断从P2.4输出方波,接到PCF8591的CLOCK,P2.6发正脉冲启动A/D转换,P2.5检测A/D转换是否完成,转换完成后,P2.7置高从P1口读取转换结果送给LED显示出来3。简易数字直流电压表的硬件电路已经设计完成,就可以选取相应的芯片和元器件,利用Proteus软件绘
21、制出硬件的原理,并仔细地检查修改,直至形成完善的硬件原理图。但要真正实现电路对电压的测量和显示的功能,还需要有相应的软件配合,才能达到设计要求。4 程序设计4.1 程序设计总方案根据模块的划分原则,将该程序划分初始化模块,A/D转换子程序和显示子程序,这三个程序模块构成了整个系统软件的主程序,如图12所示。 图12 数字式直流电压表主程序框图4.2 系统子程序设计4.2.1 初始化程序所谓初始化,是对将要用到的MCS_51系列单片机内部部件或扩展芯片进行初始工作状态设定,初始化子程序的主要工作是设置定时器的工作模式,初值预置,开中断和打开定时器等9。4.2.2 A/D转换子程序A/D转换子程序
22、用来控制对输入的模块电压信号的采集测量,并将对应的数值存入相应的内存单元,其转换流程图如图13所示。 图13 A/D转换流程图4.2.3 显示子程序显示子程序采用动态扫描实现四位数码管的数值显示,在采用动态扫描显示方式时,要使得LED显示的比较均匀,又有足够的亮度,需要设置适当的扫描频率,当扫描频率在70HZ左右时,能够产生比较好的显示效果,一般可以采用间隔10ms对LED进行动态扫描一次,每一位LED的显示时间为1ms10。在本设计中,为了简化硬件设计,主要采用软件定时的方式,即用定时器0溢出中断功能实现11s定时,通过软件延时程序来实现5ms的延时。5 仿真5.1 软件调试软件调试的主要任
23、务是排查错误,错误主要包括逻辑和功能错误,这些错误有些是显性的,而有些是隐形的,可以通过仿真开发系统发现逐步改正。Proteus软件可以对基于微控制器的设计连同所有的周围电子器件一起仿真,用户甚至可以实时采用诸如LED/LCD、键盘、RS232终端等动态外设模型来对设计进行交互仿真。Proteus支持的微处理芯片包括8051系列、AVR系列、PIC系列、HC11系列及Z80等等。Proteus可以完成单片机系统原理图电路绘制、PCB设计,更为显著点的特点是可以与u Visions3 IDE工具软件结合进行编程仿真调试8。本系统的调试主要以软件为主,其中,系统电路图的绘制和仿真我采用的是Prot
24、eus软件,而程序方面,采用的是C语言,用Keil软件将程序写入单片机。5.2 显示结果及误差分析5.2.1 显示结果1. 当IN0口输入电压值为0V时,显示结果如图14所示,测量误差为0V。图14 输入电压为0V时,LED的显示结果2.当IN0输入电压值为1.50V时,显示结果如图15所示。测量误差为0.01V。图15 输入电压为1.50V时,LED的显示结果3. 当IN0口输入电压值为3.50V时,显示结果如图16。测量误差为0.01V。图16 输入电压为3.50V时,LED的显示结果5.2.2 误差分析通过以上仿真测量结果可得到简易数字电压表与“标准”数字电压表对比测试表,如下表4所示:
25、表4 简易数字电压表与“标准”数字电压表对比测试表由于单片机STC90C51为8位处理器,当输入电压为5.00V时,PCF8591输出数据值为255(FFH),因此单片机最高的数值分辨率为0.0196V(5/255)。这就决定了电压表的最高分辨率只能到0.0196V,从上表可看到,测试电压一般以0.01V的幅度变化。从上表可以看出,简易数字电压表测得的值基本上比标准电压值偏大0-0.01V,这可以通过校正PCF8591的基准电压来解决。因为该电压表设计时直接用5V的供电电源作为电压,所以电压可能有偏差。当要测量大于5V的电压时,可在输入口使用分压电阻,而程序中只要将计算程序的除数进行调整就可以
26、了。结 论经过一段时间的努力,课程设计-基于单片机的简易数字电压表基本完成。但设计中的不足之处仍然存在。这次设计是我第一次用单片机设计电路,并用Proteus实现了仿真。在这过程中,我对电路设计,单片机的使用等都有了新的认识。通过这次设计学会了Proteus和Keil软件的使用方法,掌握了从系统的需要、方案的设计、功能模块的划分、原理图的设计和电路图的仿真的设计流程,积累了不少经验。基于单片机的数字电压表使用性强、结构简单、成本低、外接元件少。在实际应用工作应能好,测量电压准确,精度高。系统功能、指标达到了课题的预期要求、系统在硬件设计上充分考虑了可扩展性,经过一定的改造,可以增加功能。本文设
27、计主要实现了简易数字电压表测量一路电压的功能,详细说明了从原理图的设计、电路图的仿真再到软件的调试。通过本次设计,我对单片机这门课有了进一步的了解。无论是在硬件连接方面还是在软件编程方面。本次设计采用了STC90C51单片机芯片,与以往的单片机相比增加了许多新的功能,使其功能更为完善,应用领域也更为广泛。设计中还用到了模/数转换芯片PCF8591,以前在学单片机课程时只是对其理论知识有了初步的理解。通过这次设计,对它的工作原理有了更深的理解。在调试过程中遇到很多问题,硬件上的理论知识学得不够扎实,对电路的仿真方面也不够熟练。 总之这次电路的设计和仿真,基本上达到了设计的功能要求。在以后的实践中
28、,我将继续努力学习电路设计方面的理论知识,并理论联系实际,争取在电路设计方面能有所提升。参考文献1胡健.单片机原理及接口技术.北京:机械工业出版社,2004年10月2王毓银.数字电路逻辑设计.高等教育出版社,2005年12月3于殿泓、王新年.单片机原理与程序设计实验教程.西安电子科技大学出版社,2007年5月4谢维成、杨加国.单片机原理与应用及C51程序设计实例.电子工业出版社,2006年3月5李广弟.单片机基础.北京航空航天大学出版社,2007年5月6姜志海,黄玉清等著.单片机原理及应用M .北京:电子工业出版社.2005年7月7魏立峰.单片机原理及应用技术.北京大学出版社,2005年8周润
29、景.Protues在MCS-51&ARM7系统中的应用百例.第一版.北京:电子工业出版社,2006年9边春远等著.MCS-51单片机应用开发实用子程序M .北京:人民邮电出版社.2005年9月.10苗红霞.单片机实现数字电压表的软硬件设计J .河海大学常州分校学报,2002,(03).11宋凤娟,孙军,李国忠.基于89C51单片机的数字电压表设计J .工业控制计算机,2007,(04).附加程序:#include#includei2c.h/-定义使用的IO-/#define GPIO_DIG P0sbit LSA=P22;sbit LSB=P23;sbit LSC=P24;/-定义PCF859
30、1的读写地址-/#define WRITEADDR 0x90 /写地址#define READADDR 0x99 /读地址/-定义全局变量-/unsigned char code DIG_CODE17=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;/0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码unsigned char DisplayData8;/用来存放要显示的8位数的值/-声明全局函数-/void DigDisplay(); /动态显示函数void P
31、cf8591SendByte(unsigned char channel);unsigned char Pcf8591ReadByte();void Pcf8591DaConversion(unsigned char value);void DigDisplay();/-主程序-/void main()unsigned int adNum;float value;while(1)/-显示电位器电压-/Pcf8591SendByte(0); adNum = Pcf8591ReadByte(); /将转换结果读走 value = adNum * 0.01953; adNum = value * 1
32、00; DisplayData0 = DIG_CODEadNum / 1000; /发送显示数据DisplayData1 = DIG_CODEadNum % 1000 / 100 | 0x80; /或上0x80是加小数点DisplayData2 = DIG_CODEadNum % 100 / 10;DisplayData3 = DIG_CODEadNum % 10;DisplayData4 = DisplayData0;DisplayData5 = DisplayData1;DisplayData6 = DisplayData2;DisplayData7 = DisplayData3;DigD
33、isplay();/-DA输出-/Pcf8591DaConversion(adNum/2); /DAC数模转换 void Pcf8591SendByte(unsigned char channel)I2C_Start();I2C_SendByte(WRITEADDR, 1); /发送写器件地址I2C_SendByte(0x40|channel, 0); /发送控制寄存器I2C_Stop();unsigned char Pcf8591ReadByte()unsigned char dat;I2C_Start();I2C_SendByte(READADDR, 1);/发送读器件地址dat=I2C_
34、ReadByte(); /读取数据I2C_Stop(); /结束总线 return dat;void Pcf8591DaConversion(unsigned char value)I2C_Start();I2C_SendByte(WRITEADDR, 1);/发送写器件地址I2C_SendByte(0x40, 1); /开启DA写到控制寄存器I2C_SendByte(value, 0); /发送转换数值I2C_Stop();void DigDisplay()unsigned char i;unsigned int j;for(i=0;i8;i+)switch(i) /位选,选择点亮的数码管,
35、case(0):LSA=0;LSB=0;LSC=0; break;/显示第0位case(1):LSA=1;LSB=0;LSC=0; break;/显示第1位case(2):LSA=0;LSB=1;LSC=0; break;/显示第2位case(3):LSA=1;LSB=1;LSC=0; break;/显示第3位case(4):LSA=0;LSB=0;LSC=1; break;/显示第4位case(5):LSA=1;LSB=0;LSC=1; break;/显示第5位case(6):LSA=0;LSB=1;LSC=1; break;/显示第6位case(7):LSA=1;LSB=1;LSC=1; break;/显示第7位GPIO_DIG=DisplayDatai;/发送段码j=50; /扫描间隔时间设定while(j-);GPIO_DIG=0x00;/消隐