单片机电压表测量的课程设计.docx
《单片机电压表测量的课程设计.docx》由会员分享,可在线阅读,更多相关《单片机电压表测量的课程设计.docx(30页珍藏版)》请在冰豆网上搜索。
单片机电压表测量的课程设计
CHANGZHOUINSTITUTEOFTECHNOLOGY
科研实践
题目:
电压表测量
二级学院(直属学部):
延陵学院
专业:
班级:
学生姓名:
学号:
指导教师姓名:
职称:
2013年12月30日至2014年1月10日
第一章绪论
1.1课题研究目的及意义
本设计是基于单片机AT89C51的数字电压表。
硬件电路设计简单,具有读数方便、误差小、稳定性高等特点,具有较高应用价值,特别适合平常简单的测量。
采用智能化的数字仪器将是必然的趋势,它们不仅能提高测量准确度,而且能提高电测量技术的自动化程序,可以扩展成各种通用数字仪表、专用数字仪表及各种非电量的数字化仪表(如:
温度计、湿度计、酸度计、重量、厚度仪等),几乎覆盖了电子电工测量、工业测量、自动化仪表等各个领域。
从而提高计量检定人员的工作效率。
除此之外,数字电压表还有着传统指针电压表无可比拟的优点:
读数直观,准确,显示范围宽,分辨力高,输入阻抗高,功耗小,抗干扰能力强等。
因此对数字电压表做全面深入的了解是很有必要的。
但是传统的数字电压表的设计通常以大规模ASIC(专用集成电路)为核心器件,并辅以少量中规模集成电路及显示器构成,可是这种方法灵活性差,系统功能固定,难以更新扩展,不能满足日益发展的电子工业要求。
而应用微处理器(单片机)为核心单元的数字电压表,其灵活性高,系统功能扩展简单,性能稳定可靠。
在此背景下基于单片机的电压测量电路的研究是十分有意义的。
1.2数字电压表发展趋势
目前,由各种单片A/D转换器构成的数字电压表,已经被广泛用于电子及电工测量,工业自动化仪表,自动测试系统等领域,显示出强大的生命力。
数字电压表的内部核心部件是A/D转换器,转换的精度很大程度上影响着数字电压表的准确度,因而,以后数字电压表的发展就着眼在高精度和低成本这两个方面。
A/D转换器分成四种:
计数式A/D转换器、双积分式A/D转换器、逐次逼近式A/D转换器和并行式A/D转换器。
最常用的是双积分式A/D转换器和逐次逼近式A/D转换器,其中双积分式A/D转换器的主要优点是转换精度高,抗干扰性能好,价格便宜。
但是其转速度慢,因此这种转换器主要用于速度要求不高的场合。
而逐次逼近式A/D转换器速度转换速度快,但精度相对较差。
因此未来的A/D转换器将兼顾精度和速度,成本也会随着集成电路的发展而降低。
与此同时,由DVM扩展而成的各种通用及专用数字仪器仪表,也把电量及非电量测量技术提高到崭新水平。
在电量的测量中,电压,电流和频率是最基本的三个被测量。
其中,电压表的测量最为经常。
而且随着电子技术的发展,更是经常需要测量高精度的电压,所以数字电压表就成为一种比不可少的测量仪器。
另外,由于数字式仪器具有读数准确方便,精度高,误差小,灵敏度高和分变率高,测量速度快等特点而倍受用户青睐,数字式电压表就是基于这种需求而发展起来的。
第二章总体设计方案的确定
2.1数字电压表设计的具体要求
(1)以单片机为核心器件,组成一个简单的直流数字电压表;
(2)可以测量0~5V范围内的1路直流电压表;
(3)显示位数为三位;
(4)输出电压经AD转换后用LCD液晶显示器显示;
(5)误差为+-0.1V;
(6)当测量电压达到5V时LED灯闪烁,蜂鸣器发声报警;
2.2总体设计方案选定
本设计方案是利用单片机系统与模数转换芯片、显示模块等的结合构建数字电压表。
本系统以AT89C52单片机为核心控制器,电压测量电路与ADC0832相连,经A/D转换将测得的模拟电压信号转换为数字信号输人给单片机,经单片机进行信号处理后,形成精度较高的数字信号输出到LCD液晶显示器上进行显示测量误差0.1V。
根据数字电压表基本原理:
该电路通过ADC0832芯片采样输入0~5V的模拟量电压,经过模/数转换后,产生相应的数字量经过其输出通道D0--D7传送给AT89C52芯片的P1口。
该电压表的测量电路主要由三个模块组成:
A/D转换模块、数据处理模块及显示控制模块。
A/D转换主要由芯片ADC0832来完成,它负责把采集到的模拟量转换为相应的数字量再传送到数据处理模块。
数据处理则由芯片AT89C52来完成,其负责把接收到的数字量经过数据处理,再通过软件程序将采集到的数据送单片机系统存储并在显示器上显示出来。
当电压达到5V时蜂鸣器报警同时LED等闪烁。
另外,AT89C52还控制着ADC0832的工作。
显示模块主要LCD液晶显示器组成,显示测量到的电压值。
至此,一个简单的由单片机构建的直流数字电压表就完成了。
第三章电压表各部分组成
3.1电压表各组成部分电路图
电路设计由7个部分组成:
A/D转换电路、单片机、显示电路、时钟电路、复位电路、量程控制电路、电源电路、测量电压输入电路以及报警电路。
数字电压表总体设计框图如下图3-1所示。
图3-1各组成部分电路图
第四章软件主程序设计
4.1系统主程序结构图及流程图
主程序结构图如下图4-1所示:
图4-1主程序结构图
主程序流程图如下图4-2所示:
主程序采用死循环结构,在其中调用了四个子程序:
AD转换子程序,动态显示子程序,报警器子程序,首先,单片机片选A/D转换器,然后发出信号启动A/D转换。
若有,即启动信号采集,对A/D转换器的数据输出口送来的数值进行存储,数据处理完之后,将电压数值送显示器上显示出来。
当电压达到5V时蜂鸣器报警同时LED灯闪烁。
程序总体流程图如图所示:
图4-2主程序流程图
4.2系统子程序模块及流程图
4.2.1LCD液晶显示
LCD显示程序的设计一般要先确定LCD的初始化,光标定位,确定显示字符后,显示流程图如图4-3所示:
图4-3显示流程图
4.2.2ADC0832
A/D转换程序子程序用来控制对输入的模块电压信号的采集测量,并将对应的数值存入相应的内存单元,其转换流程图如图4-4所示。
图4-4A/D转换程序流程图
4.2.3报警子程序
蜂鸣器发声函数:
蜂鸣器发声的原理是不同的频率输出发出不同的声音,但是本电路对声音要求不是很高,所以只需要蜂鸣器发出声音即可,即通过函数实现蜂鸣器每秒发出0.4s声音频率。
LED灯闪烁函数:
LED灯是通过与之串联的电阻的阻值来控制其亮度。
本设计中通过蜂鸣器和LED灯相结合来实现报警效果,为实现设置最高电压阀值,当达到5V时则系统报警功能,通过调节电位器,来调节电压的大小。
图4-5报警器流程图
第五章数字电压表软件子程序设计
5.1液晶显示子程序
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#definedelay4us(){_nop_();_nop_();_nop_();_nop_();}
//LCD1602端口定义
sbitRS=P2^0;
sbitRW=P2^1;
sbitE=P2^2;
//一位整数,两位小数的数字电压表显示缓冲
ucharDisplay_Buffer[]="0.00V";
//LCD第一行显示的信息
ucharcodeLine1[]="CurrentVoltage:
";
voidDelayMS(uintms)
{
uchart;
while(ms--)for(t=0;t<120;t++);
}
//LCD忙状态检测
bitLCD_Busy_Check()
{
bitresult;
RS=0;RW=1;E=1;delay4us();result=(bit)(P0&0x80);E=0;
returnresult;
}
//写LCD控制命令
voidLCD_Write_Command(ucharcmd)
{
while(LCD_Busy_Check());
RS=0;RW=0;E=0;_nop_();_nop_();P0=cmd;delay4us();
E=1;delay4us();E=0;
}
//写LCD数据
voidLCD_Write_Data(uchardat)
{
while(LCD_Busy_Check());
RS=1;RW=0;E=0;
P0=dat;delay4us();
E=1;delay4us();E=0;
}
//设置LCD显示位置
voidSet_Disp_pos(ucharpos)
{
LCD_Write_Command(pos|0x80);
}
//LCD初始化
voidLCD_Initialise()
{
LCD_Write_Command(0x38);DelayMS
(1);
LCD_Write_Command(0x0c);DelayMS
(1);
LCD_Write_Command(0x06);DelayMS
(1);
LCD_Write_Command(0x01);DelayMS
(1);
}
voidmain()
{
uchari;
uintd;//注意d的类型
LCD_Initialise();//初始化LCD
DelayMS(10);
while
(1)
{
Set_Disp_pos(0x01);//设置显示位
i=0;
while(Line1[i]!
='\0')
LCD_Write_Data(Line1[i++]);//显示第一行字符串
Set_Disp_pos(0x46);//设置显示位置
i=0;
while(Display_Buffer[i]!
='\0')//显示电压值
LCD_Write_Data(Display_Buffer[i++]);
}
}
5.2ADC0832子程序
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
//ADC0832引脚定义
sbitCS=P1^0;
sbitDIO=P1^2;
sbitCLK=P1^1;
//一位整数,两位小数的数字电压表显示缓冲
ucharDisplay_Buffer[]="0.00V";
//获取AD转换结果(0通道)
ucharGet_AD_Result()
{
uchari,dat1=0,dat2=0;
//起始控制位
CS=0;
CLK=0;
DIO=1;_nop_();_nop_();
CLK=1;_nop_();_nop_();
CLK=0;DIO=1;_nop_();_nop_();
//第一个下降沿之前,设DI=1/0
//选择单端/差分(SGL/DIF)模式中的单端输入模式
CLK=1;_nop_();_nop_();
CLK=0;DIO=0;_nop_();_nop_();
//第二个下降沿之前,设DI=0/1,选择CH0/CH1
CLK=1;DIO=1;_nop_();_nop_();
//第三个下降沿之前,设DI=1
CLK=0;DIO=1;_nop_();_nop_();
//第4~11,共8个下降沿读数据(MSB->LSB)
for(i=0;i<8;i++)
{
CLK=1;_nop_();_nop_();
CLK=0;_nop_();_nop_();
dat1=dat1<<1|DIO;
}
//第11~18,共8个下降沿读数据(MSB->LSB)
for(i=0;i<8;i++)
{
dat2=dat2|((uchar)(DIO)<
CLK=1;_nop_();_nop_();
CLK=0;_nop_();_nop_();
}
CS=1;
//如果MSB->LSB和LSB->MSB读取的结果相同,则返回读取的结果,否则返回0
return(dat1==dat2)?
dat1:
0;
}
voidmain()
{
uchari;
uintd;
while
(1)
{
//获取AD转换值,最大值255对应于最高电压5.00V
//本例中设计为显示三个数位,故使用500
d=Get_AD_Result();
d=d*500.0/255;
//将AD转换后得到数据分解为三个数位
Display_Buffer[0]=d/100+'0';
Display_Buffer[2]=d/10%10+'0';
Display_Buffer[3]=d%10+'0';
}
}
5.3报警子程序
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
//报警器引脚定义
sbitSPK=P1^7;
sbitS=P3^5;
sbitLED=P3^0;
//发声子程序
voidAlarm(uchart)
{
uchari,j;
for(i=0;i<200;i++)
{
SPK=~SPK;
LED=~LED;
//由参数t形成不同的频率
for(j=0;j}
LED=1;
SPK=1;
}
voidmain()
{
uchari;
uintd;
LED=1;
SPK=1;
while
(1)
{
if(S==0)
Alarm(90);
}
if(d==255)
{Alarm(90);
}
}
第六章软件仿真
6.1keil软件介绍及应用
Keil软件是目前最流行开发MCS-51系列单片机的软件,这从近年来各仿真机厂商纷纷宣布全面支持Keil即可看出。
Keil是单片机普遍使用的集成开发环境编辑C源文件或汇编源文件,然后编译生成机器码。
在编译过程中,可以选择优化级别,针对代码的大小或速度进行优化。
KeilC51是美国KeilSoftware公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境、将这些部分组合在一起。
运行Keil软件需要WIN98、NT、WIN2000、WINXP等操作系统。
如果你使用C语言编程,那么Keil几乎就是你的不二之选,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。
我使用的keil软件是keiluvision4版本的,protues仿真前要通过工程选项,在output选项卡把生成.HEX文件勾选上,然后编译生成.HEX文件供protues软件仿真使用。
6.2keil软件仿真
数字电压表的Keil软件仿真步骤如下:
(1)启动uVison4IDE,新建一个项目文件,并从器件库中选择一个CPU器件;
(2)新建一个源文件并把它加入到项目中;
(3)增加并设置选择的器件的启动代码;
(4)针对目标硬件设置工具选项;
(5)编译项目并生成可以编译ROM的HEX文件。
通过上述步骤,来实现电压测量的仿真,仿真结果如下图所示:
6.2.1LCD仿真图
图6-1
6.2.2ADC0832仿真图
图6-2
6.2.3报警器仿真
图6-3
6.3keil与Proteus软件联机调试仿真
6.3.1ADC0832联机调试
图6-4
6.3.2LCD联机调试
图6-5
6.3.3ADC0832与LCD连调
图6-6
6.3.4ADC0832,LCD,,报警器三者连调
图6-7
第七章实物制作与调试
7.1电路板焊接
为了避免因焊接而造成电路不能正常工作,所以在焊接时我们应注意一些焊接注意事项:
(1)芯片与底座都是有方向的,焊接时,要严格按照PCB板上的缺口所指的方向,使芯片,底座与PCB三者的缺口都对应。
(2)焊接时,要使焊点周围都有锡,将其牢牢焊接,防止虚焊。
(3)在焊接圆形的极性电容器时(一般电容值都是比较大的),其电容器的引脚是分长短的,一长脚对应“+”号所在的孔。
(4)芯片在安装前最好先两边的针脚稍稍弯曲,使其有利于插入底座对应的插口中。
(5)电位器也是有方向的,其旋钮要与PCB板上凸出方向相对应。
(6)焊接集成电路时,先检查所用型号,引脚位置是否符合要求。
焊接时先焊边沿对脚的两只引脚,以使其定位,然后再从左到右自上而下逐个焊接。
(7)焊接后用放大镜查看焊点,检查是否有虚焊以及短路的情况的发生。
(8)接触位置:
烙铁头应同时接触要相互连接的2个被焊件,烙铁一般倾斜45度,应避免与其中以个被焊件接触。
(9)接触压力:
烙铁头与被焊件接触时应略施加压力,但以对被焊件表面不造成损伤为原则。
7.2电路板调试
本次制作调试共分为4个部分:
(1)单片机+显示器的调试
在焊接完单片机和显示器后,将显示程序拷入单片机看显示器是否能正常显示程序中的“CurrentVoltage”符号。
如果显示正常,则表示单片机与显示器之间线路正常。
(2)A/D转换调试
将ADC0832及其相关电路焊接完成后,与单片机相连,单片机录入程序,然后调节电位器看数字电压表上的值是否在0~5V之间变换。
(3)将报警电路及其相关的电路焊接好后,单片机录入程序,通过滑动电位器来调节电压使电压达到5V,观察是否蜂鸣器是否在发声,LED发光二极管是否在闪烁。
(4)程序的调试
程序调试时根据电路板来调试的,将程序拷入单片机后,在电路板上用9V的电池经7805转换成5V的电源来给电路供电。
然后调节电位器来改变电压值观察数字电压表上显示的电压值与LCD显示器上显示的电压值是否一致,如果有误差误差是否保持在+-0.1V范围之内。
第八章小结
在这短暂的两周单片机课程设计中,让我对课本的知识有了更深的认识与理解,为了更好的完成课程设计我去图书馆查阅了大量有关资料,让对充分意识到自学的重要性,刚开始时看着那些枯燥的程序代码会有点不厌烦,程序输入后进行仿真也会出现一些错误,通过不断的仔细核对后,发现那些都是自己的粗心造成的,这就提醒我们写程序时一定得认真,为了增加电路的难度性,我给电路添加了一个报警电路,这个电路的添加让我对C语言的编程有了更深的认识,同时你也克服了以往的枯燥感,让自己对编程有了更多的耐心。
同时也让我们对
Proteus仿真软件的使用更加的熟悉,在焊接电路时也遇到也了一些问题,对照原理图焊接出来的电路板实现不了预期的效果,在Proteus仿真中电压表误差值
与LCD液晶显示器上的误差满足+_0.1V,但在电路板调试中它的误差却接近大于这个值,而且电路也不稳定。
通过老师的指导发现是稳压电路的电容选值有问题,同时在原理图中的各元器件的参数值都得通过合理的计算以确保误差值满足课题要求。
另外还让我明白Proteus仿真电路与实际焊接电路在效果上还是有差距的。
在今后的学习及实践中应该更加注重理论与实际相结合。
附录
1.参考文献
[1]彭伟.单片机C语言程序设计实训100例--基于8051+Proteus仿真.
电子工业出版社.2009年
[2]程国钢.51单片机典型模块开发查询手册.电子工业出版社.2012年
[3]老杨.51单片机工程师是怎样炼成的—基于C语言+Prototeus仿真.
电子工业出版社.2012年
[4]王守中.51单片机开发入门与典型实例.人民邮电出版社.
2.实验电路元件清单
序号
元件编号
名称
规格型号
数量
备注
1
U1
单片机
AT89C52
1
2
U2
三端稳压器
7805
1
3
U3
A/D转换芯片
ADC0832
1
4
R1~R4
电阻
220,220,10K,1K
3
5
RV1,RV2
电位器
1K,10K
2
6
RP1,RP2
排阻
10K,10K
2
7
LCD1
1602液晶显示器
LM016L
1
C1~C2
电解电容
220uf,10uf
2
8
C3~C4
电容
0.1uf,30pf,30pf
3
9
X1
晶振
11.05926MHZ
1
10
Volts
直流电压表
DCVOLTMETER
1
11
LS1
蜂鸣器
BUZZER
1
12
D1
发光二极管
LED-RED
1
13
Q1
二极管
PNP
1
14
VCC
电源
1
15
BUTTON1
按钮
1
复位按钮
16
Key1
开关
1
控制电源
3.原理图
4.程序代码(C语言)
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#definedelay4us(){_nop_();_nop_();_nop_();_nop_();}
sbitCS=P1^0;
sbitDIO=P1^2;
sbitCLK=P1^1;
sbitRS=P2^0;
sbitRW=P2^1;
sbitE=P2^2;
sbitSPK=P1^7;
sbitS=P3^5;
sbitLED=P3^0;
ucharDisplay_Buffer[]="0.00V";
ucharcodeLine1[]="CurrentVoltage:
";
voidAlarm(uchart)
{
uchari,j;
for(i=0;i<200;i++)
{
SPK=~SPK;
LED=~LED;
for(j=0;j}
LED=1;
SPK=1;
}
voidDelayMS(uintms)
{
uchart;
while(ms--)for(t=0;t<120;t++);
}
bitLCD_Busy_Check()
{
bitresult;
RS=0;RW=1;E=1;delay4us();result=(bit)(P0&0x80);E=0;
returnresult;
}
voidLCD_Write_Command(ucharcmd)
{
while(LCD_Busy_Check());
RS=0;RW=0;E=0;_nop_();_nop_();P0=cmd;delay4us();
E=1;delay4us();E=0;
}
voidLCD_Write_Data(uchardat)
{
while(LCD_Busy_Check