单片机的数字温度计设计方案附代码及仿真.docx
《单片机的数字温度计设计方案附代码及仿真.docx》由会员分享,可在线阅读,更多相关《单片机的数字温度计设计方案附代码及仿真.docx(19页珍藏版)》请在冰豆网上搜索。
单片机的数字温度计设计方案附代码及仿真
单片机的数字温度计设计方案附代码及仿真
基于STC89C52的数字温度计
1、绪论………………………………………………………………………………...……….3
2、方案选择
2.1、主控芯片选择…………………………………………………………………………3
2.2、显示模块…………………………………………………………….………………...3
2.3、温度检测模块………………………………………………………………………..4
3、系统硬件设计
3.1、51单片机最小系统设计……………………………………………………….4
3.2、电源供电电路设计…………………………………………………………..……5
3.3、LCD显示电路设计…………………………………………………………..…….6
3.4、温度检测电路设计…………………………………………………….….………7
4、系统软件设计
4.1、温度传感器数据读取流程图………………………………………..……...9
4.2、系统程序设计……………………………………………………………………….10
5、编程和仿真
5.1、Keil编程软件…………………………………………………………………..…..11
5.2、proteus………………………………………………………………………………...11
5.3、仿真界面……………………………………………………………………………..11
6、总结…………………………………………………………………………..…..……..12
7、附录
附录1、原理图………………………………………………………………………….12
附录2、程序清单……………………………………………………………………..13
1、绪论
在信息高速发展的21世纪,科学技术的发展日新月异,科技的进步带动了测量技术的发展,现代控制设备的性能和结构发生了翻天覆地的变化。
我们已经进入了高速发展的信息时代,测量技术也成为当今科技的一个主流,广泛地深入到研究和应用工程的各个领域。
温度和人们的生活息息相关,温度的测量也就变得很重要。
2、系统方案选择
2.1主控芯片选择
方案一:
STC89C52RC
STC89C52RC是采用8051核的ISP在线可编程芯片,最高工作时钟频率80MHz,片内含8KB的可重复擦写1000次的Flash只读存储器,器件兼容MCS-51指令系统及8051引脚结构,芯片内集成了通用8位中央处理器和ISPFlash存储单元,具有在线可编程特定,配合PC端的控制程序即可将用户的程序代码下载进单片机内部,省去了购买通用编程器,而且速度更快。
STC89C52RC系列单片机是单时钟周期、高速、低功耗的新一代8051单片机。
方案二:
ATmega8
ATmega8是ATMAL公司在第一季度推出的一款新型AVR高档单片机。
在AVR家族中,ATmega8是一种非常特殊的单片机,它的芯片内部集成了较大容量的存储器和丰富强大的硬件接口电路,具备AVR高档单片机MEGA系列的全部性能和特点。
但由于采用了小引脚封装<为DIP28和TQFP/MLF32),因此其价格仅与低档单片机相当,再加上AVR单片机的系统内可编程特性,使得无需购买昂贵的仿真器和编程器也可进行单片机嵌入式系统的设计和开发,同时也为单片机的初学者提供了非常方便和简捷的开发环境。
由以上两种方案进行比较,我们选择STC89C52RC作为主控芯片,因为该芯片是入门级单片机,我们对该款单片机比较熟悉,而AVR单片机较为高端,这次的设计用STC89C52已经足够使用,引脚也够用,故用STC89C52作为主控芯片。
STC89C52RC价格低廉,一般5元以内能够买到,在通银买也很方便。
2.2时钟及显示模块
方案一:
数码管
数码管亮度高,显示大,特别是显示的时间很直观,价格比较便宜,但多位的数码管在动态扫描的时候会出现闪烁。
而且数码管占用的位置较大,且比较耗电。
方案二:
1602液晶屏
1602液晶屏显示清晰且不会闪烁,在需要时还能够输出字符等内容,由于液晶屏是数字式的,因此和单片机系统的接口简单,操作方便。
1602LCD液晶显示屏的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多,功耗较低。
由于其内部集成有显示芯片,程序编写简单,适用于多方面的应用。
因此由以上两种方案进行比较,我们选择方案二来设计显示模块。
1602液晶显示屏网上可购买的途径较多,价格一般在10元以内,重庆育森电子网店价格为8.5元。
通银那也有,不过可能价格要15元左右。
2.3温度检测模块
方案一:
热敏电阻+AD模块
本方案使用热敏电阻之类的器件<如AD590等模拟温度传感器)利用其感温效应,在将随被测温度变化的电压或电流采集出来,进行A/D转换后,就能够利用单片机进行数据的处理,在显示电路上能够将被测温度显示出来,这种设计需要用到A/D转换电路,感温电路比较麻烦。
方案二:
DS18B20
DS18B20数字温度传感器是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。
因此用它来组成一个测温系统,具有线路简单,在一根通信线,能够挂很多这样的数字温度计,十分方便。
它在实际应用中不需要外部任何元器件即可实现测温,测量温度范围在-55到+125摄氏度之间,
由以上两种方案进行比较,我们选择方案二来设计温度检测模块。
其中DS18B20网上报价约为5元,其中,重庆育森电子的网店较为便宜,为4.5元。
通银也有卖,价格稍微高点。
3、系统硬件设计
3.151单片机最小系统设计
单片机最小系统如下图所示:
以STC89C52单片机为核心,选用12M的晶振,这是最常见的选择,外接电容没有特别的要求,可是外接电容的大小会影响振荡器的频率高低、振荡器的稳定性和起振的快速性,因此我们选用30pf的电容作为起振电容。
复位电路为按键低电平复位,当按键按下,RET端为高电平,当高电平持续4us的时间就能够使单片机复位。
这里特别要注意的是晶振和电容的位置,它们距离单片机引脚越短越好,因为太长可能无法使单片机起振。
另外是EA端一定要接上电源,使单片机能够工作。
3.2电源供电电路设计
电源供电电路如下图所示:
我们采用4节1.5V的电池作为电源,LM2940为稳压芯片,稳压芯片两端分别接两个0.1uf和100uf的电容进行滤波,以获得更稳定的电压。
D1为电源指示灯,当开关打开,显示灯亮,表示给电路供+5V电压。
其中,LM2940作为常见的稳压芯片,比7805的转换效率要高,7805直接输入不接输出的情况下,其内部会有3mA的静态电流消耗,而2940的静态电流比7805要小的多,故选择LM2940作为稳压芯片。
4节电池装在电池盒中,在电路板下方安装,使用两套螺丝。
3.3LCD显示电路设计
1602LCD液晶屏显示电路如下图所示:
1602LCD液晶屏为5V电压驱动,带背光,可显示两行,每行16个字符,不能显示汉字。
液晶1、2端为电源;15、16为背光电源;为防止直接加5V而烧坏背光灯,在15脚串联一个1K电阻晶3端为液晶对比度调节端,经过一个10K的电位器来调节液晶显示对比度。
用于限流。
液液晶4端为向液晶控制器写数据/写命令选择端,接单片机P1.0端口。
液晶5端为读/写选择端,因为我们不需要从液晶中读取数据,只向其写入命令和数据,因此此端始终选择为写状态,即低电平接地。
液晶6端为使能信号,是操作必须的信号,接单片机的P1.1口。
3.4温度检测电路设计
温度检测电路如下图所示:
DS18B20是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,而且可根据实际要求经过简单的编程实现9~12位的数字值读数方式。
DS18B20的性能特点如下:
•独特的单线接口仅需一个端口引脚进行通讯
•简单的多点分布应用
•无需外部器件
•可经过数据线供电
•零待机功耗
•测温范围-55~+125℃,以0.5℃递增。
华氏器件-67~+2570F,以0.90F递增
•温度以9位数字量读出
•温度数字量转换时间200ms<典型值)
•用户可定义的非易失性温度报警设置
•报警搜索命令识别并标志超过程序限定温度<温度报警条件)的器件。
DS18B20内部结构主要由四部分组成:
64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20的管脚排列、各种封装形式如图3.3.1所示,DQ为数据输入/输出引脚。
开漏单总线接口引脚。
当被用着在寄生电源下,也能够向器件提供电源;GND为地信号;VDD为可选择的VDD引脚。
当工作于寄生电源时,此引脚必须接地。
其电路图如图5.3.1所示.。
图5.3.1外部封装形式
在仿真软件中如图5.3.2所示
图5.3.2
DS18B20的测温原理如图5.3.3所示,图中低温度系数晶振的振荡频率受温度的影响很小用于产生固定频率的脉冲信号送给减法计数器1,高温度系数晶振随温度变化其震荡频率明显改变,所产生的信号作为减法计数器2的脉冲输入,图中还隐含着计数门,当计数门打开时,DS18B20就对低温度系数振荡器产生的时钟脉冲后进行计数,进而完成温度测量.计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的基数分别置入减法计数器1和温度寄存器中,减法计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
减法计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当减法计数器1的预置值减到0时温度寄存器的值将加1,减法计数器1的预置将重新被装入,减法计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到减法计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温图5.3.3中的斜率累加器用于补偿和修正测温过程中的非线性其输出用,于修正减法计数器的预置值,只要计数门仍未关闭就重复上述过程,直至温度寄存器值达到被测温度值,这就是DS18B20的测温原理。
另外,由于DS18B20单线通信功能是分时完成的,有严格的时隙概念,因此读写时序很重要。
系统对DS18B20的各种操作必须按协议进行。
操作协议为:
初始化DS18B20<发复位脉冲)→发ROM功能命令→发存储器操作命令→处理数据。
图5.3.3
在正常测温情况下,DS1820的测温分辨力为0.5℃。
4、系统软件设计
4.1:
实验主程序流程图
4.2:
温度传感器数据读取流程图
5、编程和仿真
5.1编程软件Keil4
KeilC51是美国Keilsoftware公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,经过一个集成开发环境运行Keil需要win98、NT、win、winXP、win7等操作系统。
2月发布的KeiluVision4,KeiluVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方,新的用户界面能够更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁、高效的环境来开发应用程序。
5.2仿真软件proteus7.7
Proteus软件是Labcenterelectronics公司出版的EDA工具软件<该软件中国总代理为广州风标电子技术有限公司)。
它不但具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。
它是当前最好的仿真单片机及外围器件的工具。
虽然当前国内推广刚起步,但已受到单片机爱好者、从事单片机教案的教师、致力于单片机开发应用的科技工作者的青睐。
Proteus是世界上著名的EDA工具<仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。
是当前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,又增加了Cortex和DSP系列处理器,并持续增加其它系列处理器模型。
在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。
5.3仿真界面
6、总结
1、选择芯片和传感器时,够用易用就能够,综合考虑选择性价比最好的。
2、在进行电路实际制作之前,应该用仿真软件进行仿真,能够使开发进程加快。
3、在实际制作电路时,需要注意电源端和地端要检测过不导通后才能通电检测,防止烧坏芯片。
7、附录
附录1、原理图
附录2、程序清单
#include//头文件
#defineucharunsignedchar
#defineuintunsignedint
sbitrs=P2^0。
sbitlcden=P2^1。
//液晶使能端
sbitDATA=P3^7。
//DS18B20接入口
ucharFLAG_DIS=0。
ucharbai_18b20,shi_18b20,ge_18b20,num。
//定义变量
bitflag_Negative_number。
//负数标志
ucharcodetable[]={"tempreture:
"}。
//提示语
/*****一毫秒定时*****/
voiddelay_ms(uintz>
{
uintx,y。
for(x=z。
x>0。
x-->
for(y=110。
y>0。
y-->。
}
/*延时子函数*/
voiddelay(uintnum>
{
while(num-->。
}
/*液晶写命令*/
voidwrite_lcd_com(ucharcom>
{
rs=0。
lcden=0。
P0=com。
delay_ms(1>。
lcden=1。
delay_ms(1>。
lcden=0。
}
/*液晶写数据*/
voidwrite_lcd_date(uchardate>
{
rs=1。
lcden=0。
P0=date。
delay_ms(1>。
lcden=1。
delay_ms(1>。
lcden=0。
}
/*液晶初始化程序*/
voidlcd_init(>
{
write_lcd_com(0x38>。
write_lcd_com(0x0c>。
write_lcd_com(0x06>。
write_lcd_com(0x01>。
}
/*************DS18b20温度传感器函数*********************/
voidInit_DS18B20(void>//传感器初始化
{
ucharx=0。
DATA=1。
//DQ复位
delay(10>。
//稍做延时
DATA=0。
//单片机将DQ拉低
delay(80>。
//精确延时大于480us//450
DATA=1。
//拉高总线
delay(20>。
x=DATA。
//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay(30>。
}
/*温度传感器读一个字节*/
ReadOneChar(void>
{
uchari=0。
uchardat=0。
for(i=8。
i>0。
i-->
{
DATA=0。
//给脉冲信号
dat>>=1。
DATA=1。
//给脉冲信号
if(DATA>
dat|=0x80。
delay(8>。
}
return(dat>。
}
/*温度传感器写一个字节*/
voidWriteOneChar(uchardat>
{
uchari=0。
for(i=8。
i>0。
i-->
{
DATA=0。
DATA=dat&0x01。
delay(10>。
DATA=1。
dat>>=1。
}
delay(8>。
}
/*读取温度传感器温度*/
intReadTemperature(void>
{
uchara=0。
ucharb=0。
intt=0。
floattt=0。
Init_DS18B20(>。
WriteOneChar(0xCC>。
//跳过读序号列号的操作
WriteOneChar(0x44>。
//启动温度转换
Init_DS18B20(>。
WriteOneChar(0xCC>。
//跳过读序号列号的操作
WriteOneChar(0xBE>。
//读取温度寄存器等<共可读9个寄存器)前两个就是温度
a=ReadOneChar(>。
//低位
b=ReadOneChar(>。
//高位
t=b。
t<<=8。
t=t|a。
if(b&0x80>
{
t=~t+1。
flag_Negative_number=1。
}
else{flag_Negative_number=0。
}
tt=t*0.0625。
t=tt*10+0.5。
return(t>。
}
/*液晶显示温度*/
voiddis_D18B20(void>
{
inttemp。
temp=ReadTemperature(>。
//读温度
bai_18b20=temp%1000/100。
//显示十位
shi_18b20=temp%100/10。
//显示个位
ge_18b20=temp%10。
//显示十分位
if(flag_Negative_number>//负数
{
if(bai_18b20==0>//十位为0,则不显示十位
{
write_lcd_com(0x80+0x40>。
write_lcd_date(0x2D>。
write_lcd_date(0x30+shi_18b20>。
write_lcd_date(0x30+ge_18b20>。
write_lcd_date(0xDF>。
write_lcd_date(0x43>。
}
else
{
write_lcd_com(0x80+0x40>。
write_lcd_date(0x2D>。
write_lcd_date(0x30+bai_18b20>。
write_lcd_date(0x30+shi_18b20>。
write_lcd_date(0xDF>。
write_lcd_date(0x43>。
}
}
else//正数
{
if(bai_18b20==0>//十位为0,则不显示十位
{
write_lcd_com(0x80+0x40>。
write_lcd_date(0x30+shi_18b20>。
write_lcd_date(0x2E>。
write_lcd_date(0x30+ge_18b20>。
write_lcd_date(0xDF>。
write_lcd_date(0x43>。
}
else
{
write_lcd_com(0x80+0x40>。
write_lcd_date(0x30+bai_18b20>。
write_lcd_date(0x30+shi_18b20>。
write_lcd_date(0x2E>。
write_lcd_date(0x30+ge_18b20>。
write_lcd_date(0xDF>。
write_lcd_date(0x43>。
}
}
}
voidmain(>
{
lcd_init(>。
TMOD=0x01。
TH0=(65536-50000>/256。
TL0=(65536-50000>%256。
TR0=1。
ET0=1。
EA=1。
//开总中断
write_lcd_com(0x80>。
for(num=0。
num<11。
num++>
{
write_lcd_date(table[num]>。
//delay_ms(10>。
}
//dis_D18B20(>。
while(1>
{
if(FLAG_DIS==1>
{
FLAG_DIS=0。
dis_D18B20(>。
//读温度并显示
}
}
}
timer0(>interrupt1//
{
ucharcount。
TH0=(65536-50000>/256。
TL0=(65536-50000>%256。
count++。
if(count==60>//每三秒钟读一次温度传感器温度
{
FLAG_DIS=1。
count=0。
}
}