基于51单片机与DS18B20的数字温度计的设计Word格式.docx
《基于51单片机与DS18B20的数字温度计的设计Word格式.docx》由会员分享,可在线阅读,更多相关《基于51单片机与DS18B20的数字温度计的设计Word格式.docx(30页珍藏版)》请在冰豆网上搜索。
6源程序19
7总结26
参考文献:
28
1引言
随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便是不可否定的,各种数字系统的应用也使人们的生活更加舒适。
数字化控制、智能控制为现代人的工作、生活、科研等方面带来方便。
其中数字温度计就是一个典型的例子。
数字温度计与传统的温度计相比,具有读数方便、测温范围广、测温精确、功能多样话等优点。
其主要用于对测温要求准确度比较高的场所,或科研实验室使用,该设计使用STC89C52单片机作控制器,数字温度传感器DS18B20测量温度,单片机接受传感器输出,经处理用LED数码管实现温度值显示。
2设计要求
2.1基本要求
实现实时温度显示,测温范围0~500C,误差50C以内。
2.2扩展功能
温度报警,能任意设定温度范围实现声光报警;
每隔10分钟记录一次温度数据,至少能查询过去10个时刻的温度情况。
3总体方案设计
3.1方案论证
3.1.1方案一
由于本设计是测温电路,可以使用热敏电阻之类的器件,将随被测温度变化的电压或电流采样,进行A/D转换后就可以用单片机进行数据处理,实现温度显示。
这种设计需要用到A/D转换电路,增大了电路的复杂性,而且要做到高精度也比较困难。
3.1.2方案二
考虑到在单片机属于数字系统,容易想到数字温度传感器,可选用DS18B20数字温度传感器,此传感器为单总线数字温度传感器,起体积小、构成的系统结构简单,它可直接将温度转化成串行数字信号给单片机处理,即可实现温度显示。
另外DS18B20具有3引脚的小体积封装,测温范围为-55~+125摄氏度,测温分辨率可达0.0625摄氏度,其测量范围与精度都能符合设计要求。
以上两种方案相比较,第二种方案的电路、软件设计更简单,此方案设计的系统在功耗、测量精度、范围等方面都能很好地达到要求,故本设计采用方案二。
3.2总体设计框图
本方案设计的系统由单片机系统、数字温度传感器、LED显示模块、按键控制模块、温度报警模块组成,其总体架构如下图1。
单
片
机
报警电路
显示电路
驱动电路
测温电路
按键输入电路
时钟、复位电路
图1系统总体方框图
4硬件设计
4.1单片机系统
1.本设计采用STC89C52单片机作为控制器,完成所有功能的控制,包括:
●DS18B20数字温度传感器的初始化和读取温度值
●LED数码管显示驱动与控制
●按键识别和响应控制
●温度设置和报警
●温度值的存储和读取
2.单片机系统电路原理图:
图2单片机系统原理图
4.2数字温度传感器模块
4.2.1DS18B20性能
●独特的单线接口仅需一个端口引脚进行通信
●简单的多点分布应用
●无需外部器件
●可通过数据线供电
●零待机功耗
●测温范围-55~+125℃,以0.5℃递增
●可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃
●温度数字量转换时间200ms,12位分辨率时最多在750ms内把温度转换为数字
●应用包括温度控制、工业系统、消费品、温度计和任何热感测系统
●负压特性:
电源极性接反时,传感器不会因发热而烧毁,但不能正常工作
4.2.2DS18B20外形及引脚说明
图3DS18B20外形及引脚
●GND:
地
●DQ:
单线运用的数据输入/输出引脚
●VD:
可选的电源引脚
4.2.3DS18B20接线原理图
单总线通常要求接一个约4.7K左右的上拉电阻,这样,当总线空闲时,其状态为高电平。
图4DS18B20接线原理图
4.2.4DS18B20时序图
主机使用时间隙来读写DS18B20的数据位和写命令字的位。
1.初始化时序如下图:
图5DS18B20初始化时序
2.DS18B20读写时序:
图6DS18B20读写时序
4.2.5数据处理
高速暂存存储器由9个字节组成,其分配如表5所示。
当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。
单片机可通过单线接口读到该数据,读取时低位在前,高位在后。
图7字节分配
下表为12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;
如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。
例如+125℃的数字输出为07D0H,
实际温度=07D0H*0.0625=2000*0.0625=125℃。
例如-55℃的数字输出为FC90H,则应先将11位数据位取反加1得370H(符号位不变,也不作运算),
实际温度=370H*0.0625=880*0.0625=55℃。
可见其中低四位为小数位。
图8DS18B20温度数据表
4.3显示电路
LED数码管显示采用动态扫描方式,能简化电路布线,节约单片机I/O端口。
段码和位码由单片机P0送出,分别用74HC673N锁存。
图9数码管驱动显示电路
4.4声光报警电路
当温度超过设定温度值时,实现声光报警,蜂鸣器鸣叫、8个发光二极管点亮。
蜂鸣器由单片机P2^3口控制,用三极管驱动,发光二极管接单片机P1口,由74HC673N锁存。
图10声光报警电路
4.5键盘输入电路
四个键分别连接单片机P3^4、P3^5、P3^6、P3^7构成独立式键盘,分别实现加、减、报警温度设定功能键和温度查询功能键。
图11键盘输入电路
5软件设计
5.1主程序模块
主程序需要调用3个子程序,分别为:
●实时温度显示子程序:
驱动数码管把实时温度值送出在LED数码管显示
●查询记录温度值子程序:
查询过去存储的温度值,最多可查询10个值
●温度设定、报警子程序:
设定报警温度值,当温度超过该值时产生报警,即驱动蜂鸣器鸣叫、8个发光二极管发光
主程序流程图:
开始
定时器初始化、启动
显示实时温度
温度设定、报警
查询记录温度值
图12主程序流程图
5.2读温度值模块
读温度值模块需要调用4个子程序,分别为:
●DS18B20初始化子程序:
让单片机知道DS18B20在总线上且已准备好操作
●DS18B20写字节子程序:
对DS18B20发出命令
●DS18B20读字节子程序:
读取DS18B20存储器的数据
●延时子程序:
对DS18B20操作时的时序控制
1.读温度值模块流程图:
入口
数据转换处理
读取温度值高低位
跳过读序列号
DS18B20初始化
延时
启动温度转换
返回
图13读温度值子程序流程图
2.DS18B20初始化子程序流程图:
DQ为低电平?
延时15~60ms
DQ拉高电平
延时>
480ms
DQ复位0
稍延时
DQ置高电平
N
Y
图14DS18B20初始化子程序流程图
3.DS18B20写字节和读字节子程序流程图:
图15DS18B20写字节子程序流程图图16DS18B20读字节子程序流程图
5.3中断模块
中断采用T0方式1,初始值定时为50ms。
中断模块需调用两个子程序:
●读温度值子程序:
定时读取温度值,实时更新温度值
●记录温度值子程序:
定时记录温度值,供查询使用
把这两个子程序放在中断的原因是,不会因为调整报警温度或查询历史温度值而停止更新温度值和记录温度值。
中断模块流程图:
1秒?
计数值加1
定时器重置初值
中断入口
读温度值
Y
中断返回
记录温度值
图17中断模块流程图
5.4温度查询模块
温度查询模块需要接受按键输入,进入查询界面后,按加减键分别查询上一个和下一个历史温度值,并驱动数码管显示需要查询的温度值。
温度查询模块流程图如下:
功能键按下?
确认按下?
延时消抖
显示温度值与位次
加键按下?
查询下一个值
Y
减键按下?
查询上一个值
退出功能键按下?
图18温度查询模块流程图
5.5温度设定、报警模块
此模块跟温度查询模块类似,需要接受按键输入,进入模块界面后,按加减键分别上调和下调设定报警温度值,当实时温度值超过设定值时驱动蜂鸣器发声,并点亮8位发光二极管,实现声光报警。
温度设定、报警模块流程图如下:
显示设定温度值
上调设定值
下调设定值
声光报警
温度超出设定值?
取消报警
判断退出界面?
图19温度设定、报警模块流程图
5.6数码管驱动模块
本设计数码管通过锁存器接单片机P0口,采用动态扫描驱动7段LED数码管进行显示,需调用延时子程序以稳定显示。
模块流程图如下:
P0清零
关位选
送位码
开位选
P0置高
关段选
开段选
送段码
图20数码管驱动模块流程图
6源程序
#include<
reg52.h>
#defineucharunsignedchar
#defineuintunsignedint
/*************************变量定义************************************/
sbitDQ=P2^2;
//ds18b20端口
sbitbeep=P2^3;
//蜂鸣器使能端
sbitdula=P2^6;
//数码管段选使能
sbitwela=P2^7;
//数码管位选使能
sbitadd=P3^5;
//加键
sbitsub=P3^4;
//减键
sbitalarm=P3^6;
//设定报警功能键
sbitrecord=P3^7;
//查询温度记录功能键
ucharcodetabled[]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//0~9的七段数码管段码
0x40,0x63,0x39};
//-c的段码
ucharcodetablew[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//1~8个数码管的位选码
ucharrecordtable[10];
//存储过去的十个温度值
uchartemperature;
//温度值
ucharcountsec,recordnum,count;
//计数变量
uintcountmin;
ucharalanum=30;
//报警温度值,初始值为30摄氏度
ucharz=65;
//消抖延时函数入口参数
/**********************函数声明***************************************/
voiddelay1(ucharMS);
//动态扫描延时子程序
voiddelay(uchari);
//DS18B20工作延时子程序
voidInit_DS18B20();
//DS18B20初始化子程序
voidWriteOneChar(unsignedchardat);
//向DS18B20写一字节数据
ucharReadOneChar(void);
//向DS18B20读一字节数据
voidGetTemperature();
//由DS18B20产生温度值
voidDisplay(ucharwei,ucharduan);
//数码管驱动子程序
voidAlarm();
//温度报警
voidShowtemperature(uchartt);
//温度显示
voidKeeprecord();
//记录温度值
voidShowrecord();
//显示记录的温度值
/*********************主函数*******************************************/
voidmain()
{
TMOD=0x01;
//定时器初始化,定时器0方式1
TH0=(65536-50000)/256;
//50ms
TL0=(65536-50000)%256;
EA=1;
//开中断
ET0=1;
TR0=1;
//启动定时器
while
(1)
{
Showtemperature(temperature);
//显示实时温度
Alarm();
//温度设定、报警
Showrecord();
//查询温度记录值
}
}
/************************动态扫描延时函数********************************/
voiddelay1(ucharMS)
inti,j;
for(i=80;
i>
0;
i--)
for(j=MS;
j>
j--);
/************************DS18B20工作延时函数*****************************/
voiddelay(uchari)
while(i--);
/*************************DS18B20初始化函数******************************/
voidInit_DS18B20(void)
unsignedcharx=0;
DQ=1;
//DQ复位
delay(8);
//稍做延时
DQ=0;
//单片机将DQ拉低
delay(80);
//精确延时大于480us
//拉高总线
delay(10);
x=DQ;
//稍做延时后如果x=0则初始化成功x=1则初始化失败
delay(5);
while(!
x)
/*************************读一个字节**************************************/
ucharReadOneChar(void)
unsignedchari=0;
unsignedchardat=0;
for(i=8;
//给脉冲信号
dat>
>
=1;
if(DQ)
dat|=0x80;
return(dat);
/**************************写一个字节*************************************/
voidWriteOneChar(unsignedchardat)
unsignedchari=0;
for(i=8;
i>
i--)
DQ=dat&
0x01;
delay(5);
/*************************产生温度值***************************************/
voidGetTemperature()
uchartempL,tempH;
//分别为数据低位和高位
uinttemp;
Init_DS18B20();
WriteOneChar(0xCC);
//跳过读序列号的操作
WriteOneChar(0x44);
//启动温度转换
delay(200);
//跳过读序号列号的操作
WriteOneChar(0xBE);
//读取温度寄存器等(共可读9个寄存器)前两个就是温度
tempL=ReadOneChar();
//读出温度低位LSB
tempH=ReadOneChar();
//读出温度高位MSB
temp=tempH*16+tempL/16;
//tempL右移四位去掉小数位
temperature=temp&
0xff;
//测量0~50度,只取temp低八位
/**********************数码管驱动函数*************************************/
voidDisplay(ucharwei,ucharduan)
dula=0;
P0=0xff;
wela=1;
P0=tablew[wei];
wela=0;
P0=0;
dula=1;
P0=tabled[duan];
delay1
(1);
/**********************温度显示函数**************************************/
voidShowtemperature(uchartt)
Display(2,tt/10);
//显示温度数值
Display(3,tt%10);
Display(4,11);
//显示摄氏度单位
Display(5,12);
/********************温度值设定、报警函数**********************************/
voidAlarm()
bitflag;
if(alarm==0)
delay1(80);
//延时消抖
if(alarm==0)
{
flag=1;
//第一次按键进入设置
}
while(flag)
if(add==0)
delay1(z);
//延时消抖
if(add==0)
{
alanum++;
//add键按下,上调设定值
if(alanum==51)
{
alanum=0;
//最大值为50摄氏度,循环显示
}
}
if(sub==0)
if(sub==0)
alanum--;
//sub键按下,下调设定值
if(alanum==255)
alanum=50;
//最小值为0摄氏度,循环显示
Showtemperature(alanum);
Display(0,10);
//选中数码管的其他空闲位
Display(1,10);
//区别于实时温度显示“-- --”
Display(6,10);
Display(7,10);
delay1(80);
if(alarm==0)
flag=0;
//第二次按键退出设置
if(temperature>
alanum)//此处设置报警可以保证调整设定值时即可及时报警
beep=0;
//温度大于设定值,声光报警
P1=0;
else
beep=1;
//温度不大于设定值即不报警
P1=0xff;
if(temperature>
alanum)//此处设置报警即保证即使没有进入设置界面任然可以报警
beep=0;
P1=0;
else
beep=1;
P1=0xff;
}
/***********************温度记录函数**************************************/
voidKeeprecord()
uchari=9;
if(countmin==1200)//1分钟
countmin=0;
count++;
if(count==10)//10分钟
count=0;
recordnum++;
//记录一次加一,最大记录10个值
if(recordnum==10)
recordnum=10;
do
rec