资源描述
基于51单片机温度报警器
摘要:随着时代的进步和发展,单片机技术已经普及到我们生活,工作,科研,各个领域,已经成为一种比较成熟的技术,本文将介绍一种基于单片机控制的数字温度报警器,本设计属于多功能温度报警器,可以设置上下报警温度,当温度超过上限或者下限任意温度设置范围内时,开始报警。
关键词:单片机,数字显示,温度报警, DS18B20,STC89C52RC
1 引言
随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,其中数字温度报警器就是一个典型的例子,但人们对它的要求越来越高,要为现代人工作、科研、生活、提供更好的更方便的设施就需要从数单片机技术入手,一切向着数字化控制,智能化控制方向发展。
本设计所介绍的数字温度报警器与传统的温度报警器相比,具有读数方便,测温范围广,测温准确,其输出温度采用数字显示,主要用于对测温比较准确的场所,或科研实验室使用,该设计控制器使用单片机STC89C52RC,测温传感器使用DS18B20,用3位共阳极LED数码管实现温度显示,能准确达到以上要求。
2 总体设计方案
2.1数字温度报警器设计方案论证
2.1.1 方案一
由于本设计是测温电路,可以使用热敏电阻之类的器件利用其感温效应,在将随被测温度变化的电压或电流采集过来,进行A/D转换后,就可以用单片机进行数据的处理,在显示电路上,就可以将被测温度显示出来,这种设计需要用到A/D转换电路,感温电路比较麻烦。并且测量温度精度不高,有偏差。
2.1.2 方案二
进而考虑到用温度传感器,在单片机电路设计中,大多都是使用传感器,所以这是非常容易想到的,所以可以采用一只温度传感器DS18B20,此传感器可以很容易直接读取被测温度值,进行转换,就可以满足设计要求,且测量精度很高。
从以上两种方案,很容易看出,采用方案二,电路比较简单,软件设计也比较简单,故采用方案二。
2.2 方案二的总体设计框图
温度报警器电路设计总体设计方框图如图1所示,控制器采用单片机STC12C5A16S2,温度传感器采用DS18B20,用3位LED数码管实现温度显示,用一位数码管显示℃摄氏度符号。三个按键进行温度上、下限报警值设置。
主控制器
LED显示
单片机复位
温度传感器
按键调整
报警电路
时钟振荡
图1 总体设计方框图
2.2.1 主控制器
STC89C52RC单片机是以51内核为主的系列单片机,STC单片机是宏晶生产的单时钟/机器周期的单片机,是高速、低功耗、超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8—12倍,内部集成MAX810专用复位电路。4路PWM 8路高速10位A、D转换,针对电机控制,强干扰场合。STC89C52RC单片机引脚如下图:
STC89C52RC单片机主要性能
●高速:1 个时钟/ 机器周期,增强型8051 内核,速度比普通8051 快8~12 倍
●宽电压:5.5~3.8V,2.4~3.8V(STC12LE5410AD 系列)
●低功耗设计:空闲模式,掉电模式(可由外部中断唤醒)
●工作频率:0~35MHz,相当于普通8051:0~420MHz--- 实际可到48MHz,相当于8051: 0~576MHz
●时钟:外部晶体或内部RC 振荡器可选,在ISP 下载编程用户程序时设置
● 16K 字节片内Flash 程序存储器,擦写次数10 万次以上
● 512 字节片内RAM 数据存储器
●芯片内EEPROM 功能
● ISP / IAP,在系统可编程/ 在应用可编程,无需编程器/ 仿真器
● 10 位ADC,8 通道, STC12C5A16S2 系列为8 位ADC。4 路PWM 还可当4 路D/A 使用
● 2 个硬件16 位定时器,兼容普通8051 的定时器。4 路PCA 还可再实现4 个定时器
●硬件看门狗(WDT)
●高速SPI 通信端口
●全双工异步串行口(UART),兼容普通8051 的串口
●先进的指令集结构,兼容普通8051指令集
4 组8 个8 位通用工作寄存器(共32 个通用寄存器)
有硬件乘法/ 除法指令
●通用I/O 口(27/23/15 个),复位后为: 准双向口/ 弱上拉(普通8051 传统I/O 口)
可设置成四种模式:准双向口/ 弱上拉,推挽/ 强上拉,仅为输入/ 高阻,开漏每个I/O 口驱动能力均可达到20mA,但整个芯片最大不得超过55mA。
2.2.2 显示电路
显示电路采用3位共阳LED数码管做为温度值显示。用三个8550PNP三极做为每一位LED管的驱动电路,这样使得数码管电流量更大,亮度更亮。一位共阳极数码管显示℃摄氏度符号,使得整个显示电路更加人性化。
2.2.3温度传感器
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。DS18B20的性能特点如下:
●独特的单线接口仅需要一个端口引脚进行通信;
●多个DS18B20可以并联在惟一的三线上,实现多点组网功能;
●无须外部器件;
●可通过数据线供电,电压范围为3.0~5.5V;
●零待机功耗;
●温度以9或12位数字;
●用户可定义报警设置;
●报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件;
●负电压特性,电源极性接反时,温度计不会因发热而烧毁,但不能正常工作;
DS18B20采用3脚PR-35封装或8脚SOIC封装,其内部结构框图如图2所示。
C
64
位
ROM
和
单
线
接
口
高速缓存
存储器与控制逻辑
温度传感器
高温触发器TH
低温触发器TL
配置寄存器
8位CRC发生器
Vdd
I/O
图2 DS18B20内部结构
64位ROM的结构开始8位是产品类型的编号,接着是每个器件的惟一的序号,共有48位,最后8位是前面56位的CRC检验码,这也是多个DS18B20可以采用一线进行通信的原因。温度报警触发器TH和TL,可通过软件写入户报警上下限。
DS18B20温度传感器的内部存储器还包括一个高速暂存RAM和一个非易失性的可电擦除的EERAM。高速暂存RAM的结构为8字节的存储器,结构如图3所示。头2个字节包含测得的温度信息,第3和第4字节TH和TL的拷贝,是易失的,每次上电复位时被刷新。第5个字节,为配置寄存器,它的内容用于确定温度值的数字转换分辨率。DS18B20工作时寄存器中的分辨率转换为相应精度的温度数值。该字节各位的定义如图3所示。低5位一直为1,TM是工作模式位,用于设置DS18B20在工作模式还是在测试模式,DS18B20出厂时该位被设置为0,用户要去改动,R1和R0决定温度转换的精度位数,来设置分辨率。
温度 LSB
温度 MSB
TH用户字节1
TL用户字节2
配置寄存器
保留
保留
保留
CRC
图3 DS18B20字节定义
由表1可见,DS18B20温度转换的时间比较长,而且分辨率越高,所需要的温度数据转换时间越长。因此,在实际应用中要将分辨率和转换时间权衡考虑。
高速暂存RAM的第6、7、8字节保留未用,表现为全逻辑1。第9字节读出前面所有8字节的CRC码,可用来检验数据,从而保证通信数据的正确性。
当DS18B20接收到温度转换命令后,开始启动转换。转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的第1、2字节。单片机可以通过单线接口读出该数据,读数据时低位在先,高位在后,数据格式以0.0625℃/LSB形式表示。
当符号位S=0时,表示测得的温度值为正值,可以直接将二进制位转换为十进制;当符号位S=1时,表示测得的温度值为负值,要先将补码变成原码,再计算十进制数值。表2是一部分温度值对应的二进制温度数据。
表1 DS18B20温度转换时间表
DS18B20完成温度转换后,就把测得的温度值与RAM中的TH、TL字节内容作比较。若T>TH或T<TL,则将该器件内的报警标志位置位,并对主机发出的报警搜索命令作出响应。因此,可用多只DS18B20同时测量温度并进行报警搜索。
在64位ROM的最高有效字节中存储有循环冗余检验码(CRC)。主机ROM的前56位来计算CRC值,并和存入DS18B20的CRC值作比较,以判断主机收到的ROM数据是否正确。
DS18B20的测温原理是这这样的,器件中低温度系数晶振的振荡频率受温度的影响很小,用于产生固定频率的脉冲信号送给减法计数器1;高温度系数晶振随温度变化其振荡频率明显改变,所产生的信号作为减法计数器2的脉冲输入。器件中还有一个计数门,当计数门打开时,DS18B20就对低温度系数振荡器产生的时钟脉冲进行计数进而完成温度测量。计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的一个基数分别置入减法计数器1、温度寄存器中,计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
减法计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当减法计数器1的预置值减到0时,温度寄存器的值将加1,减法计数器1的预置将重新被装入,减法计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到减法计数器计数到0时,停止温度寄存器的累加,此时温度寄存器中的数值就是所测温度值。其输出用于修正减法计数器的预置值,只要计数器门仍未关闭就重复上述过程,直到温度寄存器值大致被测温度值。
表2 一部分温度对应值表
温度/℃
二进制表示
十六进制表示
+125
0000 0111 1101 0000
07D0H
+85
0000 0101 0101 0000
0550H
+25.0625
0000 0001 1001 0000
0191H
+10.125
0000 0000 1010 0001
00A2H
+0.5
0000 0000 0000 0010
0008H
0
0000 0000 0000 1000
0000H
-0.5
1111 1111 1111 0000
FFF8H
-10.125
1111 1111 0101 1110
FF5EH
-25.0625
1111 1110 0110 1111
FE6FH
-55
1111 1100 1001 0000
FC90H
另外,由于DS18B20单线通信功能是分时完成的,它有严格的时隙概念,因此读写时序很重要。系统对DS18B20的各种操作按协议进行。操作协议为:初使化DS18B20(发复位脉冲)→发ROM功能命令→发存储器操作命令→处理数据。
图4 DS18B20与单片机的接口电路
2.3 DS18B20温度传感器与单片机的接口电路
DS18B20可以采用两种方式供电,一种是采用电源供电方式,此时DS18B20的1脚接地,2脚作为信号线,3脚接电源。另一种是寄生电源供电方式,如图4 所示单片机端口接单线总线,为保证在有效的DS18B20时钟周期内提供足够的电流,可用一个MOSFET管来完成对总线的上拉。
当DS18B20处于写存储器操作和温度A/D转换操作时,总线上必须有强的上拉,上拉开启时间最大为10us。采用寄生电源供电方式时VDD端接地。由于单线制只有一根线,因此发送接口必须是三态的。
2.2.3 报警电路
采用有源蜂鸣器做为报警器,用一个PNP三极管8550做为驱动。蜂鸣器可以在被测温度超过上限温度或者低于下限温度时,发出报警鸣叫声音。
2.2.4 按键电路
三个轻触开关组成按键电路,因为都是独立的按键所以采用直接接地的方法,这样电路比较简单,达到了效果。三个独立式按键可以分别调整温度的上下限报警温度,当按下设置键一次,数码管显示HXX℃且 LED数码管闪烁,这时可以调整报警上限温度值。按下设置键第二次,L XX℃且数码管闪烁,这时可以调整报警下限温度值。通过“加键”可以对设置数值加。通过“减键”可以对设置数值减。每按一次减1。最高可加到100,最低可减到0。
2.4 系统整体硬件电路
2.4.1 主板电路
系统整体硬件电路包括,传感器数据采集电路,温度显示电路,上下限报警调整电路,单片机主板电路等,如图5 所示:
图5 单片机主板电路
图5 中没有采用按键做为复位电路,直接采用电容充电的方式做为复位,在每上电时单片机复位一次这样就可以达到重启单片机的效果。
2.4.2 电源电路
整个电路采用+5V供电,通过USB接口供电,一个发光二极管做为电源指示灯。
3 系统软件算法分析
系统程序主要包括主程序,读出温度子程序,温度转换命令子程序,计算温度子程序,显示数据刷新子程序等。
3.1主程序
主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值,温度测量每1s进行一次。这样可以在一秒之内测量一次被测温度,其程序流程见图7所示。
Y
发DS18B20复位命令
发跳过ROM命令
发读取温度命令
读取操作,CRC校验
9字节完?
CRC校验正?确?
移入温度暂存器
结束
N
N
Y
初始化
调用显示子程序
1S到?
初次上电
读出温度值温度计算处理显示数据刷新
发温度转换开始命令
N
Y
N
Y
图7 主程序流程图 图8读温度流程图
3.2读出温度子程序
读出温度子程序的主要功能是读出RAM中的9字节,在读出时需进行CRC校验,校验有错时不进行温度数据的改写。其程序流程图如图8示。
3.3温度转换命令子程序
温度转换命令子程序主要是发温度转换开始命令,当采用12位分辨率时转换时间约为750ms,在本程序设计中采用1s显示程序延时法等待转换的完成。温度转换命令子程序流程图如图9所示:
发DS18B20复位命令
发跳过ROM命令
发温度转换开始命令
结束
图9 温度转换流程图
3.4 计算温度子程序
计算温度子程序将RAM中读取值进行BCD码的转换运算,并进行温度值正负的判定,其程序流程图如图10所示:
开始
温度零下?
温度值取补码置“—”标志
计算小数位温度BCD值
计算整数位温度BCD值
结束
置“+”标志
N
Y
温度数据移入显示寄存器
十位数0?
百位数0?
十位数显示符号百位数不显示
百位数显示数据(不显示符号)
结束
N
N
Y
Y
图10 计算温度流程图 图11 显示数据刷新流程图
3.5 显示数据刷新子程序
显示数据刷新子程序主要是对显示缓冲器中的显示数据进行刷新操作,当最高显示位为0时将符号显示位移入下一位。程序流程图如图11。
4 总结与体会
经过将近三周的单片机课程设计,终于完成了我的数字温度报警器的设计,虽然没有完全达到设计要求,但从心底里说,还是高兴的,毕竟这次设计把实物都做了出来,高兴之余不得不深思呀!
在本次设计的过程中,我发现很多的问题,虽然以前还做过这样的设计但这次设计真的让我长进了很多,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事,举个例子,以前写的那几次,数据加减时,我用的都是BCD码,这一次,我全部用的都是16进制的数直接加减,显示处理时在用除法去删分,感觉效果比较好,有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西是很难理解的,更谈不上掌握。
从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习单机片机更是如此,程序只有在经常的写与读的过程中才能提高,这就是我在这次课程设计中的最大收获。
参考文献
[1] 李朝青.单片机原理及接口技术(简明修订版).杭州:北京航空航天大学出版社,1998
[2] 李广弟.单片机基础[M].北京:北京航空航天大学出版社,1994
[3] 阎石.数字电子技术基础(第三版). 北京:高等教育出版社,1989
[4] 廖常初.现场总线概述[J].电工技术,1999.
附录:程序
/*---/*-------------------------------
温度控制器V1.5
显示为三个共阳极LED
温度传感器用单总线DS18B20
CPU为2051,四个按键,分别为UP,DOWN,SET
温度调节上限为125度,下限为-55度
只能用于单只18B20
-------------------------------*/
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
code unsigned char seg7code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0xff,0xbf}; //不带小数点的共阳数码管段码
code unsigned char seg7codeB[]={0x40,0x79,0x24,0x30,0x19,0x12,
0x02,0x78,0x00,0x10,0xff,0xbf}; //带小数点的共阳数码管段码
sbit Key_UP=P1^6; //上调温度
sbit Key_DOWN=P1^7; //下调温度
sbit Key_SET=P1^5; //设定键(温度设定,长按开电源)
sbit LEDOneC=P2^6; //LED DS1控制(百位)
sbit LEDTwoC=P2^5; //LED DS2控制(十位)
sbit LEDThreeC=P2^4; //LED DS3控制(个位)
sbit DATA=P2^0; //DS18B20接入口
sbit Bell=P3^7;//Bell蜂鸣器输出
sbit Hled=P3^5;
sbit Lled=P3^6;
unsigned int shangxian=38; //上限报警温度,默认值为38
unsigned int xiaxian=5; //下限报警温度,默认值为5
uchar data wendu[3];
uchar user_set[4];
unsigned char fg=0,fg1;
unsigned int temp,num,i;
int tvalue;//存放温度数值
float tt;//温度处理的中间变量
void delay(uint num)//延时函数
{
while(num--);
}
void Init_DS18B20(void)//初始化DS18B20温度传感器
{
uchar DQ=0;
DATA=1; //DS18B20函数复位
delay(10); //稍做延时
DATA=0; //单片机将DQ拉低
delay(80); //精确延时大于480毫秒
DATA=1; //拉高总线
delay(20);
DQ=DATA; //稍做延时后 如果X=0则初始化成功,X=1则初始化失败
delay(30);
}
Readonuchar(void)//读一个字节
{
uchar i=0;
uchar dat=0;
for(i=8;i>0;i--)
{
DATA=0; //给脉冲信号
dat>>=1; //将dat中高位移出去,同时这句其延时的作用
DATA=1; //给脉冲信号
if(DATA) //读走一位
dat|=0x80;
delay(8);
}
return(dat);
}
void writeonechar(uchar dat)//写一个字节
{
uchar i=0;
for(i=8;i>0;i--)
{
DATA=0;
DATA=dat&0x01;
delay(10);
DATA=1;
dat>>=1;
}
delay(8);
}
int ReadTemperature(void) //读取温度
{
uchar a=0;
uchar b=0;
Init_DS18B20();
writeonechar(0xCC); //跳过读序列号操作
writeonechar(0x44); //启动转换温度
Init_DS18B20();
writeonechar(0xCC); //跳过读序列号操作
writeonechar(0xBE); //读取温度寄存器(共可读9个寄存器)前两个技术温度
a=Readonuchar(); //低位
b=Readonuchar(); //高位
tvalue=b; //高位赋给int型变量
tvalue<<=8; //高位左移八位
tvalue=tvalue|a; //两个char型变量组合一个int型变量
tt=tvalue*(0.625); //最低位是 0.625
tvalue=tt; //
return(tvalue); //返回数值tvalue
}
//********************显示函数****************
void Wendu_display(void)
{
LEDOneC=0;
P0=seg7code[temp%1000/100];
delay(500);
LEDOneC=1;
P0=0xff;
LEDTwoC=0;
P0=seg7codeB[temp%100/10];
delay(500);
LEDTwoC=1;
P0=0xff;
LEDThreeC=0;
P0=seg7code[temp%10];
delay(500);
LEDThreeC=1;
P0=0xff;
}
/****进入设置显示画面******/
void Xiaxian_disp(void) //下限设置界面
{
LEDOneC=0;
P0=0xc7;
delay(50);
LEDOneC=1;
P0=0xff;
LEDTwoC=0;
P0=seg7code[xiaxian/10];
delay(50);
LEDTwoC=1;
P0=0xff;
LEDThreeC=0;
P0=seg7code[xiaxian%10];
delay(50);
LEDThreeC=1;
P0=0xff;
}
void Shangxian_disp(void) //上限设置界面
{
LEDOneC=0;
P0=0x89;
delay(50);
LEDOneC=1;
P0=0xff;
LEDTwoC=0;
P0=seg7code[shangxian/10];
delay(50);
LEDTwoC=1;
P0=0xff;
LEDThreeC=0;
P0=seg7code[shangxian%10];
delay(50);
LEDThreeC=1;
P0=0xff;
}
/********中断按键扫描**********/
void Timer0(void) interrupt 1
{
TH0=0X53;
TL0=0X32;
if(Key_SET==0)
delay(200);
if(Key_SET==0)
{
fg++;
if(fg==3)
{
fg=0;
}
while(Key_SET==0);
}
if(fg==0)
{
temp=ReadTemperature();//读温度
Wendu_display(); //显示温度
if(tvalue>shangxian*10)Hled=0;
else Hled=1;
if(tvalue<xiaxian*10)Lled=0;
else Lled=1;
if((tvalue>shangxian*10)||(tvalue<xiaxian*10))Bell=0;
else Bell=1;
}
if(fg==1) //设置上限报警值
delay(20);
if(fg==1)
{
if(Key_UP==0)
delay(10000);
if(Key_UP==0)
{
shangxian++;
}
if(Key_DOWN==0)
delay(10000);
if(Key_DOWN==0)
{
shangxian--;
}
if(shangxian>99)shangxian=99;
if(shangxian<=xiaxian)shangxian=xiaxian;
}
if(fg==2) //设置下限报警值
delay(20);
if(fg==2)
{
if(Key_UP==0)
delay(10000);
if(Key_UP==0)
{
xiaxian++;
}
if(Key_DOWN==0)
delay(10000);
if(Key_DOWN==0)
{
if(xiaxian<1)xiaxian=1;
xiaxian--;
}
if(xiaxian>=shangxian)xiaxian=shangxian;
//if(xiaxian<1)xiaxian=0;
}
}
/********循环显示设置温度*****/
void key_scan(void)
{
while(fg==1)
{
Shangxian_disp();
delay(10);
}
while(fg==2)
{
Xiaxian_disp();
delay(10);
}
}
/*********主函数*******/
void main(void)
{
TMOD=0x00; //设置定时器T0为模式0
TH0=0X53;
TL0=0X32;
TR0=1;
ET0=1;
EA=1;
for(i=100;i>0;i--)
{
temp=ReadTemperature();//读温度
// Lled=0;
// delay(1000);
}
// Lled=1;
while(1)
{
key_scan();
}
}
25
展开阅读全文