51单片机温度计.docx
《51单片机温度计.docx》由会员分享,可在线阅读,更多相关《51单片机温度计.docx(23页珍藏版)》请在冰豆网上搜索。
51单片机温度计
目前,单片机已经在测控领域获得了广泛的应用,它除了可以测量电信以外,还可以用于温度,湿度等非电信号的测量。
能独立工作的单片机温度检测和温度控制系统已经广泛用于很多领域。
单片机是一种特殊的计算机,它是在一块半导体的芯片上集成了CPU,存储器,RAM,ROM及输入与输出接口电路,这种芯片成为:
单片机。
由于单片机的集成度高,功能强,通用性好,特别它具有体积小,重量轻,能耗低,价格便宜,抗干扰能力强和使用仿版等方面的优点,是它迅速的得到了推广和应用,目前已经成为测量控制系统中的优良机种和新电子产品中的关键部件。
单片机已不仅仅局限于小系统的概念,现已广泛应用于家用电器,机电产品,办公自动化产品,机器人,儿童玩具,航天器等领域。
这次我们的模电设计,就是用的单片机实现温度的控制,传统的温度传感器大多以热敏电阻作为温度传感器,但热敏电阻的可靠性差,测量温度准确率低,而且必须经过专门的接口电路转换成数字信号才能由单片机进行处理。
本次我和陆路裕同学采用的正是DS18B
20数字温度传感器来实现基于51单片机的温度计的设计。
传统的温度计有发映速度慢,读数麻烦,测量精度不高,误差大等缺点而下面利用集成温度传感器DS18B20设计并制作了一款基于AT89C51的4位数码管现实的数字温度计,其电路简单,软硬件结构模块化,易于实现。
该数字温度计利用温度传感器及接口电路完成温度的测量并转换成模拟电压信号,经由模数转换器转换成单片机能够处理的数字信号,然后送到单片机中进行处理变换,最后将温度值显示在数码管上。
系统以单片机为控制核心,加上DS18B20温度传感器,4位温度数据显示的共阴极数码管,及外围电源和报警电路组成。
2.设计任务及要求
2.1设计任务
现代生活中,多功能的数字温度计能给我们的生活带来很大的方便,支持"一线总线"接口的温度传感器简化了数字温度计的设计,降低了成本;以美国MAXIM/DALLAS半导体公司的单总线温度传感器DS18B20为核心,以ATMEL公司的AT89S52位控制器设计的AT89S51为控制器设计的DS18B20温度传感器结构简单,测温准确,具有一定控制功能的智能温度控制器。
此次我们的设计,就是用单片机实现温度的控制,传统的温度检测大多以热敏电阻为温度传感器,但热敏电阻的可靠习惯差,测量温度准确率低,而且必须经过专门的接口电路转换成数字信号才由单片机处理。
本次采用DS18B20温度传感器来实现基于51单片机的数字温度计的设计。
该数字温度计利用DS18B20温度传感器及其接口电路完成温度的测量并转换成模拟电压信号,经由数模转换器转换成单片机能够处理的数字信号,送到单片机进行处理变换,最后经过三极管的放大显示在共阴极数码管上。
系统以51单片机为控制核心,加上测温电路,AD数模转换器,4位温度数据显示数码管以及外围电源时钟电路组成。
2.2设计要求
$5V电源(+-0.3v)用于温度计的供电;
$温度采集采用DS18B20温度传感器;数字式温度计要求测温围为-5~35°C,精度误差在0.1°C以。
$4位数字共阴极数码管显示;
$3个按键,分别为复位重置按键,温度上限设置按钮,温度下限设置按钮;
$设计温度显示计(含报警功能)电路图,并且用相关软件进行仿真演示;
$演示成功之后,设计和绘制软件流程图,并用C语言进行程序编写;
$准备元器件材料,按照电路图焊接电路,并进行调试;
$分析讨论,总结经验,对成果进行优化,撰写报告;
3设计总体方案及器材选用分析
3.1方案论证
方案一:
提到温度的检测,我们首先会考虑到传统的测温元件有热电阻和热电偶,而热点阻和热电偶测出的一般都是电压,进行A/D转换后,讲究可以用单片机进行数据的处理,在显示电路上就可以将温度显示出来,而这需要比较多的外部的硬件的支持,硬件电路复杂(需要用到A/D转换电路,感温电路),软件调试也复杂,制作成本也非常高。
所以这个设计理论不符合这次我们对产品的要求,应继续来考虑另一可行方案。
方案二:
进而考虑到使用温度传感器,在单片机电路设计中,大多时使用传感器,这是我们应该想到的,所以可以采用一只温度传感器DS18B20,此温度传感器,可以很容易读出北侧温度值,进行转换,就可以满足设计要求,另外我们还别出心裁的在电路中加入了温度报警电路,可以实时监测温度,这在实际生产生活中有很大应用。
将两个方案进行比较可以看出,方案二原理简明易行,测量精度高,故我们采用方案二。
3.2方案的总体设计框图
根据系统的设计要求,选择DS18B20作为本系统的温度传感器,选择单片机AT89C51为测控系统的核心来完成数据采集、处理、显示、报警等功能。
选用数字温度传感器DS18B20,省却了采样/保持电路、运放、数/模转换电路以及进行长距离传输时的串/并转换电路,简化了电路,缩短了系统的工作时间,降低了系统的硬件成本。
该系统的总体设计思路如下:
温度传感器DS18B20把所测得的温度发送到AT89C51单片机上,经过51单片机处理,将把温度在显示电路上显示,本系统显示器用4位共阴LED数码管以动态扫描法实现。
检测围5摄氏度到38摄氏度。
数字温度计总体电路结构框图如图1所示。
:
4.2单片机主控制器系统
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
4.3温度传感器模块
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
DS18B20的性能特点如下:
●独特的单线接口方式仅需要一个端口引脚进行通信;
●多个DS18B20可以并联在唯一的三线上,实现多点组网功能;
●无需外部器件;
●可通过数据线供电,电压围:
3.0~5.5V;
●测温围-55℃~+125℃,在-10~+85℃时精度为±0.5℃
●零待机功耗
●温度以9或12位数字量读出;
●用户可定义的非易失性温度报警设置
●报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件
●负电压特性,电源极性接反时,温度计不会因发热而烧毁,但不能正常工作
DS18B20采用3脚PR-35封装或8脚SOIC封装,其部结构框图如图3所示:
图3DS18B20部结构框图
64b闪速ROM的结构如下:
开始8位是产品类型的编号,接着是每个器件的惟一的序号,共有48位,最后8位是前面56位的CRC检验码,这也是多个DS18B20可以采用一线进行通信的原因。
温度报警触发器TH和TL,可通过软件写入户报警上下限。
主机操作ROM的命令有五种,如表1所列
DS18B20温度传感器的部存储器还包括一个高速暂存RAM和一个非易失性的可电擦除的EERAM。
高速暂存RAM的结构为8字节的存储器,结构如图4所示。
前2个字节包含测得的温度信息,第3和第4字节TH和TL的拷贝,是易失的,每次上电复位时被刷新。
第5个字节,为配置寄存器,它的容用于确定温度值的数字转换分辨率。
DS18B20工作时寄存器中的分辨率转换为相应精度的温度数值.
温度低位LSB
温度高位MSB
TH
TL
配置
保留
保留
保留
8位CRC
当DS18B20接收到温度转换命令后,开始启动转换。
转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的第1,2字节。
单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式以0.0625℃/LSB形式表示。
温度值格式如下:
这是12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。
图中,S表示位。
对应的温度计算:
当符号位S=0时,表示测得的温度植为正值,直接将二进制位转换为十进制;当S=1时,表示测得的温度植为负值,先将补码变换为原码,再计算十进制值。
例如+125℃的数字输出为07D0H,+25.0625℃的数字输出为0191H,-25.0625℃的数字输出为FF6FH,-55℃的数字输出为FC90H。
DS18B20温度传感器主要用于对温度进行测量,数据可用16位符号扩展的二进制补码读数形式提供,并以0.0625℃/LSB形式表示。
表2是部分温度值对应的二进制温度表示数据。
DS18B20完成温度转换后,就把测得的温度值与RAM中的TH、TL字节容作比较,若T>TH或T因此,可用多只DS18B20同时测量温度并进行告警搜索。
在64位ROM的最高有效字节中存储有循环冗余校验码(CRC)。
主机根据ROM的前56位来计算CRC值,并和存入DS18B20中的CRC值做比较,以判断主机收到的ROM数据是否正确。
3)DS18B20测温原理
DS18B20的测温原理如图5所示,图中低温度系数晶振的振荡频率受温度的影响很小用于产生固定频率的脉冲信号送给减法计数器1,高温度系数晶振随温度变化其震荡频率明显改变,所产生的信号作为减法计数器2的脉冲输入,图中还隐含着计数门,当计数门打开时,DS18B20就对低温度系数振荡器产生的时钟脉冲后进行计数,进而完成温度测量.计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的基数分别置入减法计数器1和温度寄存器中,减法计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
减法计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当减法计数器1的预置值减到0时温度寄存器的值将加1,减法计数器1的预置将重新被装入,减法计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到减法计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温图2中的斜率累加器用于补偿和修正测温过程中的非线性其输出用,于修正减法计数器的预置值,只要计数门仍未关闭就重复上述过程,直至温度寄存器值达到被测温度值,这就是DS18B20的测温原理。
另外,由于DS18B20单线通信功能是分时完成的,他有严格的时隙概念,因此读写时序很重要。
系统对DS18B20的各种操作必须按协议进行。
操作协议为:
初始化DS18B20(发复位脉冲)→发ROM功能命令→发存储器操作命令→处理数据。
在正常测温情况下,DS1820的测温分辨力为0.5℃,可采用下述方法获得高分辨率的温度测量结果:
首先用DS1820提供的读暂存器指令(BEH)读出以0.5℃为分辨率的温度测量结果,然后切去测量结果中的最低有效位(LSB),得到所测实际温度的整数部分Tz,然后再用BEH指令取计数器1的计数剩余值Cs和每度计数值CD。
考虑到DS1820测量温度的整数部分以0.25℃、0.75℃为进位界限的关系,实际温度Ts可用下式计算:
Ts=(Tz-0.25℃)+(CD-Cs)/CD
4.5显示模块
采用4位共阴极LED数码管显示,采用共阴极数码管需要加入负载驱动,所以我们在焊接时加上了四个三极管以驱动保证能够正常显示,这在后面我们会用图来说明。
此外我们设置了KEY1,KEY2,KEY3三个按钮,KEY1
是复位键,KEY2是增加上线温度报警键,KEY3是减少下线温度报警键。
4.6电源模块
5V直流电源(+-0.3v)用于该温度计的供电;
5系统程序的设计
系统程序主要包括主程序,读出温度子程序,温度转换命令子程序,计算温度子程序,报警子程序和显示数据刷新子程序等.
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#include"DS18B20.c"
uintmun=0;
uchartime_wang=0;
unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
sbitB0=P1^0;
sbitB1=P1^1;
sbitB2=P1^2;
sbitB3=P1^3;
sbitK1=P3^1;
sbitK2=P3^2;
sbitK3=P3^3;
sbitjingbao=P3^7;
ucharwendu_H=38;
ucharwendu_L=5;
ucharSHOW=0;
/**************************************************************
*名称:
Delay_NS()
*功能:
长软件1ms延时
***************************************************************/
voiddelay(uintms)
{
uchari;
while(ms--)//ms毫秒软件延时
{
for(i=63;i>1;i--);
}
}
//--------------------------------------------------------------------------------------------
voidSys_Initial(void)
{
TMOD=0x22;//定时器1工作方式2,定时器0工作方式1
TH0=0x3C;
TL0=0xB0;//50ms
ET0=1;//开定时器T0中断
TR0=1;//开定时器T0
EA=1;//开总中断
}
//************************************************************************************************
voidtimer0()interrupt1using2
{
TH0=0xff;
TL0=0xa0;
time_wang++;
if(SHOW==0)
{
if(time_wang==5)
{
P2=0xff;
B0=0;B1=1;B2=1;B3=1;
P2=~table[mun/1000];
}
if(time_wang==10)
{
P2=0xff;
B0=1;B1=0;B2=1;B3=1;
P2=~table[(mun%1000)/100];
}
if(time_wang==15)
{
P2=0xff;
B0=1;B1=1;B2=0;B3=1;
P2=(~table[(mun%100)/10])&0x7f;
}
if(time_wang==20)
{
time_wang=0;
P2=0xff;
B0=1;B1=1;B2=1;B3=0;
P2=~table[mun%10];
}
}
if(SHOW==1)
{
if(time_wang==5)
{
P2=0xff;
B0=0;B1=1;B2=1;B3=1;
P2=~0x38;
}
if(time_wang==10)
{
P2=0xff;
B0=1;B1=0;B2=1;B3=1;
P2=0xff;
}
if(time_wang==15)
{
P2=0xff;
B0=1;B1=1;B2=0;B3=1;
P2=~table[wendu_L/10];
}
if(time_wang==20)
{
time_wang=0;
P2=0xff;
B0=1;B1=1;B2=1;B3=0;
P2=~table[wendu_L%10];
}
}
if(SHOW==2)
{
if(time_wang==5)
{
P2=0xff;
B0=0;B1=1;B2=1;B3=1;
P2=~0x76;
}
if(time_wang==10)
{
P2=0xff;
B0=1;B1=0;B2=1;B3=1;
P2=0xff;
}
if(time_wang==15)
{
P2=0xff;
B0=1;B1=1;B2=0;B3=1;
P2=~table[wendu_H/10];
}
if(time_wang==20)
{
time_wang=0;
P2=0xff;
B0=1;B1=1;B2=1;B3=0;
P2=~table[wendu_H%10];
}
}
}
//---------------------------------
//**********************************************************
voidkey_scan(void)
{
if(!
K1)//启动
{
delay(100);
SHOW++;
if(SHOW==3)SHOW=0;
}
if(!
K2)
{
delay(100);
if(SHOW==0)return;
if(SHOW==1)
{
if(wendu_L==(wendu_H-1))
return;
else
wendu_L++;
}
if(SHOW==2)
{
if(wendu_H<99)
wendu_H++;
}
}
if(!
K3)
{
delay(100);
if(SHOW==0)return;
if(SHOW==1)
{
if(wendu_L>0)
wendu_L--;
}
if(SHOW==2)
{
if(wendu_H==(wendu_L+1))
return;
else
wendu_H--;
}
}
}
//************************************************************************************************
voidmain(void)//主函数
{
//uchari;
Sys_Initial();//单片机初始化,开定时器0
while
(1)
{
wendu_read();
mun=wendu*10+xiaoshu;
if(wendu>wendu_L&&wendu{
jingbao=0;
}
else
jingbao=1;
key_scan();
}
}
//DS18B20的最底层函数。
sbitDS=P3^6;
#defineucharunsignedchar
uchartempL=0xaa;//温度传感器传回来的温度低八位
uchartempH=0x50;//温度传感器传回来的温度高八位
ucharwendu,xiaoshu;
//-------------------------------------------------
voiddelay1(ucharcount)
{
while(count>0)count--;
}
voidreset(void)//sendresetandinitializationcommand
{
DS=0;
delay1(100);
DS=1;
delay1(4);
delay1(20);
}
bitread_bit(void)//readabit
{
bittemp;
DS=0;
_nop_();
DS=1;
_nop_();
temp=DS;
EA=1;
delay1(20);
EA=0;
returntemp;
}
ucharread_byte(void)//readabytedate
{
uchari,byte=0;
bitj;
for(i=0;i<8;i++)
{
byte=_cror_(byte,1);
j=read_bit();
if(j==0)byte=byte|0x00;
elsebyte=byte|0x80;
}
returnbyte;
}
voidwrite_byte(ucharcommand)//writeabytetods18b20
{
uchari;
for(i=0;i<8;i++)
{
if((command&0x01)==0)
{
DS=0;
delay1(8);
DS=1;
_nop_();
}
else
{
DS=0;
_nop_();
DS=1;
delay1(8);
}
command=_cror_(command,1);
}
}
//-------------------------------------------------
//DS18B20读温度程序
uintreadtemperature()
{
uinttemperature;
EA=0;
reset();//初始化
EA=1;
delay1
(1);//转换需要一点时间,延时大一点,应该大于500us吧
EA=0;
write_byte(0xcc);//写SKIPROM(跳过检查ROM序列,因为我们一般只有一个DS18B20!
)
EA=1;
delay1
(1);//转换需要一点时间,延时大一点,应该大于500us吧
EA=0;
write_byte(0x44);//写启动温度转换
EA=1;
delay1(12);//转换需要一点时间,延时大一点,应该大于500us吧
EA=0;
reset();//初始化
write_byte(0xcc);//写SKIPROM(跳过检查ROM序列,因为我们一般只有一个DS18B20!
)
EA=1;
del