基于单片机的DS18B20温度传感器.docx
《基于单片机的DS18B20温度传感器.docx》由会员分享,可在线阅读,更多相关《基于单片机的DS18B20温度传感器.docx(31页珍藏版)》请在冰豆网上搜索。
基于单片机的DS18B20温度传感器
《基于AT89C52单片机的DS18B20温度传感器》
设计报告
设计时间:
12月22日~12月26日
班级:
姓名:
报告页数:
25页
工业大学课程设计报告
设计题目:
基于AT89C52单片机的DS18B20温度传感器
学院:
专业:
班
学号:
:
(合作者____号____)
成绩评定_______
教师签名_______
摘要:
随着时代的进步和发展,单片机技术已经普及到我们生活、工作、科研、各个领域,已经成为一种比较成熟的技术,本次课程设计主要设计一个基于89C51单片机的数字温度传感器DS18B20开发测温系统,重点学习掌握对传感器在单片机下的硬件连接,软件编程以及各模块系统流程的详尽分析,提高电路设计的技巧。
该系统可以方便的实现实现温度采集和显示,它使用起来相当方便,具有精度高、量程宽、灵敏度高、体积小、功耗低等优点,适合于我们日常生活和工、农业生产中的温度测量,也可以当作温度处理模块嵌入其它系统中,作为其他主系统的辅助扩展。
DS18B20与AT89C52结合实现最简温度检测系统,该系统结构简单,抗干扰能力强,有广泛的应用前景。
关键词:
单片机;温度采集;AT89C52;DS18B20;
4.6PCB电路板的制作…………………………………………….19
附录:
元器件清单
1设计任务
采用方案一(温度传感器LM35,3位半A/D转换器)或者方案二(52单片机,温度传感器DS18B20),数码管或者液晶显示,设计一个日常温度数字计。
产品指标及技术要求:
温度显示围:
0~45摄氏度
数字显示分辨率:
0.1摄氏度
精度误差:
小于等于0.5摄氏度
电路工作电源可在5~9V围工作
2总体方案设计
2.1方案论证
2.1.1方案一
采用温度传感器LM35,3位半A/D转换器,数码管或者液晶显示,设计一个日常温度数字计。
本方案主要利用硬件电路连接,通过更改电路器件参数,显示出3位半温度,并没有利用软件编程。
本方案设计简单,但电路复杂,这种设计需要用到A/D转换电路,增大了电路的复杂性,而且要做到高精度也比较困难。
并且基本电路中所需要的器件和芯片成本不便宜。
2.1.2方案二
采用AT89C52单片机,温度传感器DS18B20,数码管或者液晶显示,设计一个日常温度数字计。
本方案主要利用硬件电路连接,通过软件编程,显示出3位半温度。
本方案设计比较难,要同时考虑硬件的连接和软件编程,但电路简单,另外DS18B20具有3引脚的小体积封装,测温围为-55~+125摄氏度,测温分辨率可达0.0625摄氏度,其测量围与精度都能符合设计要求。
并且基本电路中所需要的器件和芯片成本便宜。
以上两种方案相比较,第二种方案的电路、软件设计更简单,成本便宜,此方案设计的系统在功耗、测量精度、围等方面都能很好地达到要求,故本设计采用方案二。
1
2.2总体设计框图及电路
本方案设计的系统由单片机系统、数字温度传感器、液晶1602显示模块、时钟模块组成,其总体架构如下图1。
电路设计:
AT89C52单片机最小系统+DS18B20数字温度传感器模块+液晶1602驱动显示模块
图1单片机最小系统
图2DS18B20数字温度传感器模块
2
图3液晶1602驱动显示模块
3硬件设计
3.1单片机系统
AT89C52单片机引脚介绍
AT89C52为8位通用微处理器,采用工业标准的C51核,在部功能及管脚排布上与通用的89C52相同,其主要用于会聚调整时的功能控制。
功能包括对会聚主IC部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。
主要管脚有:
XTAL1(19脚)和XTAL2(18脚)为振荡器输入输出端口,外接11.0592MHz晶振。
RST/Vpd(9脚)为复位输入端口,外接电阻电容组成的复位电路。
VCC(40脚)和VSS(20脚)为供电端口,分别接+5V电源的正负端。
P0~P3为可编程通用I/O脚,其功能用途由软件编程定义。
图4晶振电路图图5复位电路图
3
图6单片机管脚图
3.2数字温度传感器模块
3.2.1DS18B20性能
●独特的单线接口仅需一个端口引脚进行通信
●简单的多点分布应用
●无需外部器件
●可通过数据线供电
●零待机功耗
●测温围-55~+125℃,以0.5℃递增
●可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃
●温度数字量转换时间200ms,12位分辨率时最多在750ms把温度转换为数字
●应用包括温度控制、工业系统、消费品、温度计和任何热感测系统
●负压特性:
电源极性接反时,传感器不会因发热而烧毁,但不能正常工作
3.2.2DS18B20外形及引脚说明
●GND:
地
●DQ:
单线运用的数据输入/输出引脚
●VD:
可选的电源引脚
4
图7DS18B20外形及引脚
3.2.3DS18B20接线原理图
单总线通常要求接一个约4.7K左右的上拉电阻,这样,当总线空闲时,其状态为高电平。
图8DS18B20接线原理图
3.2.4DS18B20时序图
主机使用时间隙来读写DS18B20的数据位和写命令字的位。
1.初始化时序
5
图9DS18B20初始化时序
2.DS18B20读写时序
图10DS18B20读写时序
3.2.5数据处理
高速暂存存储器由9个字节组成,其分配如表5所示。
当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。
单片机可通过单线接口读到该数据,读取时低位在前,高位在后。
6
图11字节分配
下表为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℃。
可见其中低四位为小数位。
图12DS18B20温度数据表
3.31602液晶显示电路
LCD1602引脚功能说明
第1脚:
VSS为电源地
第2脚:
VDD接5V电源正极
7
第3脚:
V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
第4脚:
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
第5脚:
RW为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
第6脚:
E(或EN)端为使能(enable)端。
第7~14脚:
D0~D7为8位双向数据端。
第15~16脚:
空脚或背灯电源。
15脚背光正极,16脚背光负极
图131602液晶显示电路及实物图
4软件设计
4.1主程序模块
主程序需要调用3个子程序,分别为:
●实时温度显示子程序:
驱动液晶1602把实时温度值送出在液晶屏显示
●中断定时及显示子程序:
驱动液晶1602把定时时钟送出在液晶屏显示
●温度设定、报警子程序:
设定报警温度值,当温度超过或者低于该值时产生报警,即驱动液晶屏显示不同的界面
主程序流程图:
8
4.2读温度值模块
读温度值模块需要调用4个子程序,分别为:
●DS18B20初始化子程序:
让单片机知道DS18B20在总线上且已准备好操作
●DS18B20写字节子程序:
对DS18B20发出命令
●DS18B20读字节子程序:
读取DS18B20存储器的数据
●延时子程序:
对DS18B20操作时的时序控制
读温度值模块流程图:
图14读温度值子程序流程图
9
4.3中断模块
中断采用T0定时器方式1,初始值定时为50ms,并不断计数。
来模拟时钟
中断模块流程图:
图15中断模块流程图
4.4温度报警模块
设定报警温度上限值,当温度超过该值时产生报警,驱动液晶1602在液晶屏第一行显示“weater:
hot”的界面
设定报警温度下限值,当温度低于该值时产生报警,驱动液晶1602在液晶屏第一行显示“weater:
cold”的界面
当温度在上限值和下限值之间时,不产生报警,驱动液晶1602在液晶屏第一行显示“HappyEveryday!
”的界面
4.5程序开发
10
软件程序使用C语言编写开发,开发环境软件为Keil4
应用Keil进行软件仿真开发的主要步骤为:
编写源程序并保存—建立工程并添加源文件—设置工程—编译/汇编、连接,产生目标文件—程序调试。
Keil使用“工程”(Project)的概念,对工程(而不能对单一的源程序)进行编译/汇编、连接等操作。
工程的建立、设置、编译/汇编及连接产生目标文件的方法非常易于掌握。
首先选择菜单File-New…,在源程序编辑器中输入汇编语言或C语言源程序(或选择File-Open…,直接打开已用其它编辑器编辑好的源程序文档)并保存,注意保存时必须在文件名后加上扩展名.asm(.a51)或.c;然后选择菜单Project-NewProject…,建立新工程并保存(保存时无需加扩展名,也可加上扩展名.uv2);工程保存后会立即弹出一个设备选择对话框,选择CPU后点确定返回主界面。
这时工程管理窗口的文件页(Files)会出现“Target1”,将其前面+号展开,接着选择SourceGroup1,右击鼠标弹出快捷菜单,选择“AddFiletoGroup‘SourceGroup1’”,出现一个对话框,要求寻找并加入源文件(在加入一个源文件后,该对话框不会消失,而是等待继续加入其它文件)。
加入文件后点close返回主界面,展开“SourceGroup1”前面+号,就会看到所加入的文件,双击文件名,即可打开该源程序文件。
紧接着对工程进行设置,选择工程管理窗口的Target1,再选择Project-OptionforTarget‘Target1’(或点右键弹出快捷菜单再选择该选项),打开工程属性设置对话框,共有8个选项卡,主要设置工作包括在Target选项卡中设置晶振频率、在Debug选项卡中设置实验仿真板等,如要写片,还必须在Output选项卡中选中“CreatHexFi”;其它选项卡容一般可取默认值。
工程设置后按F7键(或点击编译工具栏上相应图标)进行编译/汇编、连接以及产生目标文件。
成功编译/汇编、连接后,还须通过编程器将.hex目标文件烧写入单片机中才能观察目标样机真实的运行状况。
如下为编译成功,并生成hex文件的界面
程序代码:
/***********************************************************************************************************
基于AT89C52单片机的时钟+LCD1602显示+DS18B20温度
***********************************************************************************************************/
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitDQ=P2^7;
11
sbitrs=P2^4;//lcd1602数据、命令选择端
sbitrw=P2^3;//lcd1602读、写选择线
sbitlcde=P2^2;//lcd1602使能线
uchartp,tpx,num,count,miao,fen,shi;
ucharcodetable[]="HappyEveryday!
";
ucharcodetable1[]=":
:
";
ucharcodetable2[]="weather:
cold";
ucharcodetable3[]="weather:
hot";
/***************************************************************************************************
延时函数
***************************************************************************************************/
voiddelay(uintz)//ms级延时函数
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*voiddelay1()//us级延时函数1
{;;}*/
voiddelay2(uinti)//us级延时函数2
{
while(i--);
}
/**************************************************************************************************
ds18b20初始化
***************************************************************************************************/
voidinit_ds18b20()//初始化
{
DQ=1;//数据线拉高
delay2(8);//大约80us
DQ=0;//数据线拉低
12
delay2(80);//(480us~960us)大约798us
DQ=1;//数据线拉高
delay2(14);//(15us~60us+40us~240us)大约154us
}
/**************************************************************************************************
ds18b20读一个字节
***************************************************************************************************/
ucharread_ds18b20_byte()
{
uchari=0;
uchardat=0;
for(i=0;i<8;i++)//一个字节为8位,所以循环8次
{
DQ=0;//数据线拉低
dat=dat>>1;//字节右移一位
DQ=1;//数据线拉高
if(DQ==1)//判断读回是否为1
{
dat=dat|0x80;//最高位或上一个1,使得最高位变为1
}
delay2(4);//延时6us
}
returndat;//循环8次完成一个字节,并返回数据
}
/******************************************************************************************************
ds18b20写一个字节
*******************************************************************************************************/
voidwrite_ds18b20_byte(uchardate)
{
uchari=0;
for(i=0;i<8;i++)//一个字节为8位,所以循环8次
{
DQ=0;//数据线拉低
DQ=date&0x01;//取出数据的最低位送到数据线
delay2(5);//66us,大于60us
DQ=1;//数据线拉高
13
date=date>>1;//字节右移一位,接着取第二位
}
}
/*******************************************************************************************************
ds18b20读取温度
********************************************************************************************************/
intread_ds18b20_temp()//考虑到温度可能为负值,所以使用int型
{
uchara=0;//用于读取低8位
uintb=0;//用于读取高8位
uintt=0;//用于组成新的温度
init_ds18b20();//初始化
write_ds18b20_byte(0xcc);//忽略ROM指令
write_ds18b20_byte(0x44);//进行温度转换
init_ds18b20();//初始化
write_ds18b20_byte(0xcc);//忽略ROM指令
write_ds18b20_byte(0xbe);//读暂存器指令
a=read_ds18b20_byte();//读取低8位
b=read_ds18b20_byte();//读取高8位
a=a&0x00ff;//将低8位与上0x00ff,设定低8位
b=(b&0x000f)<<8;//将高8位与上0x0000f,去掉高4位,左移取12位,设定为高8位
t=a|b;//两者或组成一个16位的字节
returnt;//将温度值返回
}
/*******************************************************************************************************
LCD写入一个字节命令函数
********************************************************************************************************/
14
voidwritecom(uchar)
{
rs=0;//写指令
rw=0;//进行写操作
lcde=0;
delay(5);
lcde=0;
P1=;
delay(5);
lcde=1;//使能端一个上升沿,把命令写入
delay(5);
lcde=0;
}
/*******************************************************************************************************
LCD写入一个字节数据函数
*******************************************************************************************************/
voidwritedate(uchardate)
{
rs=1;//写数据
rw=0;//进行写操作
delay(5);
lcde=0;
P1=date;
delay(5);
lcde=1;//使能端一个上升沿,把数据写入
delay(5);
lcde=0;
}
/*******************************************************************************************************
温度显示函数
********************************************************************************************************/
voidwendudisplay()
{
uinttp,tpz;
uinttp2,tpshi,tpge,tpxiao;
15
tp=read_ds18b20_temp();//读温度
tp2=tp&0x000f;
tpxiao=tp2*6/10;
tpz=(tp&0x0ff0)>>4;
tpshi=tpz/10;//取十位
tpge=tpz%10;//取个位
writecom(0x80+0x40+10);
writedate(tpshi+0x30);//显示温度十位
writedate(tpge+0x30);//显示温度个位
writedate('.');
writedate(tpxiao+0x30);
writedate(0xdf);
writedate('C');//显示温度符号
if(tpz<15)
{
writecom(0x80);
for(num=0;num<16;num++)
{
writedate(table2[num]);
delay(5);
}
}
if((tpz<25)&&(tpz>15))
{
writecom(0x80)