基于单片机的DS18B20测温系统设计.docx
《基于单片机的DS18B20测温系统设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的DS18B20测温系统设计.docx(22页珍藏版)》请在冰点文库上搜索。
基于单片机的DS18B20测温系统设计
1-Wire总线与DS18B20应用仿真
文章出处:
发布时间:
2008/08/15|1527次阅读|0次推荐|0条留言
Samtec连接器完整的信号来源开关,电源限时折扣最低45折每天新产品时刻新体验ARMCortex-M3内核微控制器最新电子元器件资料免费下载完整的15A开关模式电源首款面向小型化定向照明应用代替
1-Wire总线的基本通信协议
作为一种单主机多从机的总线系统,在一条1-Wire总线上可挂接的从器件数量几乎不受限制。
为了不引起逻辑上的冲突,所有从器件的1-Wire总线接口都是漏极开路的,因此在使用时必须对总线外加上拉电阻(一般取5kΩ左右)。
主机对1-Wire总线的基本操作分为复位、读和写三种,其中所有的读写操作均为低位在前高位在后。
复位、读和写是1-Wire总线通信的基础,下面通过具体程序详细介绍这3种操作的时序要求。
(程序中DQ代表1-Wire总线,定义为P1.0,uchar定义为unsignedchar)
11-Wire总线的复位
复位是1-Wire总线通信中最为重要的一种操作,在每次总线通信之前主机必须首先发送复位信号。
如程序1.1所示,产生复位信号时主机首先将总线拉低480~960μs然后释放,由于上拉电阻的存在,此时总线变为高电平。
1-Wire总线器件在接收到有效跳变的15~60μs内会将总线拉低60~240μs,在此期间主机可以通过对DQ采样来判断是否有从器件挂接在当前总线上。
函数Reset()的返回值为0表示有器件挂接在总线上,返回值为1表示没有器件挂接在总线上。
程序1.1总线复位
ucharReset(void)
{
uchartdq;
DQ=0;//主机拉低总线
delay480μs();//等待480μs
DQ=1;//主机释放总线
delay60μs();//等待60μs
tdq=DQ;//主机对总线采样
delay480μs();//等待复位结束
returntdq;//返回采样值
}
21-Wire总线的写操作
由于只有一条I/O线,主机1-Wire总线的写操作只能逐位进行,连续写8次即可写入总线一个字节。
如程序1.2所示,当MCS-51单片机的时钟频率为12MHz时,程序中的语句_nop_();可以产生1μs的延时,调用此函数时需包含头文件“intrins.h”。
向1-Wire总线写1bit至少需要60μs,同时还要保证两次连续的写操作有1μs以上的间隔。
若待写位wbit为0则主机拉低总线60μs然后释放,写0操作完成。
若待写位wbit为1,则主机拉低总线并在1~15μs内释放,然后等待60μs,写1操作完成。
程序1.2向总线写1bit
voidWritebit(ucharwbit)
{
_nop_();
//保证两次写操作间隔1μs以上
DQ=0;
_nop_();
//保证主机拉低总线1μs以上
if(wbit)
{
//向总线写1
DQ=1;
delay60μs();
}
else
{
//向总线写0
delay60μs();
DQ=1;
}
}
31-Wire总线的读操作
与写操作类似,主机对1-Wire总线的读操作也只能逐位进行,连续读8次,即可读入主机一个字节。
从1-Wire总线读取1bit同样至少需要60μs,同时也要保证两次连续的读操作间隔1μs以上。
如程序1.3所示,从总线读数据时,主机首先拉低总线1μs以上然后释放,在释放总线后的1~15μs内主机对总线的采样值即为读取到的数据。
程序1.3从总线读1bit
ucharReadbit()
{
uchartdq;
_nop_();
//保证两次连续写操作间隔1μs以上
DQ=0;
_nop_();
//保证拉低总线的时间不少于1μs
DQ=1;
_nop_();
tdq=DQ;
//主机对总线采样
delay60μs();
//等待读操作结束
returntdq;
//返回读取到的数据
}
数字温度传感器DS18B20
1DS18B20的基本特性
●采用1-Wire总线接口,可以方便实现多点测温。
●与主机连接方便,除5kΩ的总线上拉电阻外无须其他额外器件。
●电源电压范围为3.0~5.5V,与3.3V和5V数字系统均可很好地兼容。
●测量范围为-55~+125℃,分辨率为9~12位可编程。
●通过编程可设置温度报警上下限,设置值掉电不丢失。
●内部集成了用于器件寻址的64bit光刻ROM编码。
2DS18B20中的存储器
在DS18B20中共有三种存储器,分别是ROM、RAM、EEPROM,每种存储器都有其特定的功能,可查阅相关资料。
31-Wire总线ROM功能命令
在DS18B20内部光刻了一个长度为64bit的ROM编码,这个编码是器件的身份识别标志。
当总线上挂接着多个DS18B20时可以通过ROM编码对特定器件进行操作。
ROM功能命令是针对器件的ROM编码进行操作的命令,共有5个,长度均为8bit(1Byte)。
①读ROM(33H)
当挂接在总线上的1-Wire总线器件接收到此命令时,会在主机读操作的配合下将自身的ROM编码按由低位到高位的顺序依次发送给主机。
总线上挂接有多个DS18B20时,此命令会使所有器件同时向主机传送自身的ROM编码,这将导致数据的冲突。
②匹配ROM(55H)
主机在发送完此命令后,必须紧接着发送一个64bit的ROM编码,与此ROM编码匹配的从器件会响应主机的后续命令,而其他从器件则处于等待状态。
该命令主要用于选择总线上的特定器件进行访问。
③跳过ROM(CCH)
发送此命令后,主机不必提供ROM编码即可对从器件进行访问。
与读ROM命令类似,该命令同样只适用于单节点的1-Wire总线系统,当总线上有多个器件挂接时会引起数据的冲突。
④查找ROM(F0H)
当主机不知道总线上器件的ROM编码时,可以使用此命令并配合特定的算法查找出总线上从器件的数量和各个从器件的ROM编码。
⑤报警查找(ECH)
此命令用于查找总线上满足报警条件的DS18B20,通过报警查找命令并配合特定的查找算法,可以查找出总线上满足报警条件的器件数目和各个器件的ROM编码。
4DS18B20器件功能命令
与1-Wire总线相关的命令分为ROM功能命令和器件功能命令两种,ROM功能命令具有通用性,不仅适用于DS18B20也适用于其他具有1-Wire总线接口的器件,主要用于器件的识别与寻址;器件功能命令具有专用性,它们与器件的具体功能紧密相关。
下面是DS18B20的器件功能命令。
①启动温度转换(44H)
该命令发送完成后,主机可以通过调用Readbit()函数判断温度转换是否完成,若Readbit()的返回值为0则表示转换正在进行,若Readbit()的返回值为1则表示转换完成。
②读RAM(BEH)
该命令发送完成后,主机可以通过调用Readbit()函数将DS18B20中RAM的内容从低位到高位依次读出。
③写RAM(4EH)
该命令发出后,主机随后写入1-Wire总线的3字节将依次被存储到DS18B20的报警上限、报警下限和配置寄存器中。
④复制RAM(48H)
该命令会将DS18B20的报警上限、报警下限和配置寄存器中的内容复制到EEPROM中。
该命令发出后,主机可以通过调用Readbit()函数判断复制操作是否完成,若Readbit()的返回值为1,则表示复制操作完成。
⑤回读EEPROM(B8H)
该命令会将存储在EEPROM中的报警上限、报警下限和配置寄器的内容回读到RAM中,主机可以通过调用Readbit()函数判断回读操作是否完成,若Readbit()的返回值为1则表示回读操作完成。
DS18B20在上电时会自动进行一次回读操作。
图1主机与DS18B20的通信流程图
5主机与DS18B20的通信流程
如图1所示,主机通过1-Wire总线接口对DS18B20的每次访问都以复位信号和ROM功能命令开始,访问的结束位置是不确定的,这与具体的功能命令相关。
图中圆角矩形中的操作与主机发送的功能命令相对应,随着功能命令的不同圆角矩形中的操作有时可以被省略。
对总线上的DS18B20来说,复位信号意味着又一次通信的开始,器件对此的响应是拉低总线以告知主机自身的存在,然后准备接收ROM功能命令。
多点测温系统仿真实例
DS18B20是一种比较廉价的温度传感器,其封封装形式如图2所示。
在Proteus中包含有DS18B20的仿真模型,这使得相关程序的调试变得简单方便。
下面以一个实例介绍用Proteus仿真多点测温系统的步骤。
图2DS18B20封装形式
①绘制仿真原理图
如图3所示,在本实例中以单片机AT89C52和8个DS18B20构成了一个多点测温系统。
为了有足够的空间存储各个DS18B20的ROM编码和温度值,在实例中用一片8KB的SRAM芯片6116对单片机的RAM进行了扩展。
②设置DS18B20仿真模型的属性
首先右击选中protues编辑区中的DS18B20仿真模型然后再左击,此时弹出如图4所示的属性设置对话框。
其中,FamilyCode是器件的家族码,对于DS18B20来说是28H。
ROMSerialNumber对应于器件的48bit序列号,格式为十六进制,在填写过程中要保证同一条1-Wire总线上所有仿真模型的ROMSerialNumber都不相同。
AutomaticSerialization设置为No时仿真模型将使用ROMSerialNumber中的序列号,设置为Yes时模型的序列号将由仿真环境自动生成,在此设置为Yes,这样可以免去手动修改ROMSerialNumber的麻烦。
CurrentValue中是仿真模型当前的温度值。
Cranularity中是单击仿真模型的温度值增减按钮时温度值的改变量,在此设置为1.1。
其他选项保持默认即可。
单击OK按钮,设置完成。
图3多点测温系统仿真原理图
③编制源程序
主机是通过Reset()、Readbit()、Writebit()三种基本操作与1-Wire总线进行通信的,只要这三个函数的时序准确,那么对于有一定C语言编程基础的用户来说程序其他部分的编写将不是难事,按照前面介绍的流程向总线发送功能命令并进行相应读写操作即可。
多点测温系统编程的难点在于器件的查找,系统上电时主机首先要查找总线上挂接着多少个1-Wire器件并将各个器件的ROM编码读入单片机的RAM中,这需要一套复杂的算法,限于篇幅关于此算法在此不再详述。
本仿真实例大体工作过程如图3右下角注释部分所示,“查找总线上所有器件的ROM编码并存储”这一步可以由ucharB20ReadROM(ucharB20ROM[]函数完成,该函数的返回值是查找到的器件数目,各个器件的ROM编码将存储在二维数组B20ROM[]中。
图4DS18B20仿真模型属性设置
“统一开始温度转换”的通信流程为:
发送复位信号;发送跳过ROM(CCH)命令;发送启动温度转换(44H)命令。
“逐器件读取温度值”的通信流程为:
发送复位信号;发送匹配ROM(55H)命令;发送第i(i=0~7)个器件的ROM编码;发送读RAM(BEH)命令;读取2字节,其中低字节在前,高字节在后,读取到的值符合温度值数据格式。
④在Proteus中添加监视变量
为了检验程序运行的正确与否,通常的做法是将运行结果通过单片机的UART接口输出到虚拟终端上,这种方法的缺点是会占用一定的单片机资源,在此介绍另外一种程序调试技巧——监视变量。
在Proteus的运行状态下点击Debug→WatchWindow会弹出监视窗口(WatchWindow),然后按下Alt+A键会弹出如图5所示的添加存储器条目对话框(AddMemoryItem)。
所谓监视变量也就是监视相应存储单元中的内容,图5中
图5添加存储器条目对话框
Memory用于选择待监视变量所在的存储器;Name用于填写变量名称,为了含义清晰该名称最好与源程序中定义的变量名称一致;Address用于填写待监视变量的地址;DataType和DisplayFomat用于设置数据格式和显示格式。
设置完成后单击Add按钮即可添加一个监视变量。
在本实例中将测量到的温度值转化成ACSLL码字符串的格式存储在二维数组TempBuffer中,因此DataType选择为ASCLLZString,WatchWindow的最终结果如图6所示。
Value一栏中显示的即为8个DS18B20测量到的温度值,单击仿真模型的温度增减按钮温度值的改变会自动映射在WatchWindow中。
图6监视窗口
图6中TempBuffer[i](i=0~7)的地址在Keil中可以按以下步骤得到:
●单击Keil工具栏中的按钮,进入调试状态。
●通过View→OutputWindow菜单调出Keil的OutputWindow,并选中Command标签。
●在OutputWindow的命令输入区输入TempBuffer[i]然后回车即可得到TempBuffer[i]的地址,在本实例中i=0~7。
对于非数组类型的变量在输入时需要在变量名前加取地址符号&,如图7所示。
图7变量地址的获取
**************************************************************************************************************************************************************
范例二 环境温度监测系统
一、设计要求
环境温度监测系统广泛地用于住宅小区、楼宇建筑和设备内部等。
其主要功能和指标如下:
1、可以监测8点环境温度信号,可以扩充;
2、测量范围为0.00℃~99.9℃,可以扩充到-55℃~+125℃,精度为±0.5℃;
3、用4位数码管进行循环显示,其中最高位显示通道提示符A~H,低3位显示实际温度值,每秒切换一个通道进行轮流显示;
4、可以随时查看指定通道的温度值(扩充功能)。
二、设计指导
1、方案选择
该系统主要由温度检测和数据采集两部分组成。
下面列举两种实现方案:
方案一:
温度检测可以使用低温热偶或铂电阻,数据采集部分则使用带有A/D通道的单片机。
考虑到一般的A/D输入通道都只能接收大信号,所以还应设计相应的放大电路。
此方案的软件简单,但硬件复杂,且检测点数追加时,成本会有较大增长幅度。
方案二:
使用单片机和单总线温度传感器构成。
单总线温度传感器可以采用DALLAS公司生产的DS18B20系列,这类温度传感器直接输出数字信号,且多路温度传感器可以挂在1条总线上,共同占用单片机的1条I/O线即可实现接口。
在提升单片机I/O线驱动能力的前提下,理论上可以任意扩充检测的温度点数。
比较两个方案后可以发现,方案二更适合于用作本系统的实施方案。
尽管方案二不需要A/D,但考虑到系统扩充等因素,单片机可以选用ADuc812,以便于在需要的时候扩充参数存储、D/A输出、温度控制等功能。
2、硬件设计
采用方案二的硬件设计比较简单,系统构成如图1所示,原理图如图5所示。
单片机的P0口用作4位数码管的段码线,P3.4~P3.7用作4位数码管的位选线(ADuc812的P3有允许8mA的灌电流,可以不加驱动)。
P2.4用作DS18B20的数据输入/输出线。
DS18B20的引脚定义和封装形式之一如图2所示。
DQ为数字信号输入/输出端;GND为电源地;VDD为外接电源
。
DS18B20的光刻ROM中存有64位序列号,它可以看作是该DS18B20的地址序列码。
64位光刻ROM的排列是:
开始8位(28H)是产品类型标号,接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。
光刻ROM的作用是使每一个DS18B20拥有惟一的地址序列码,以确保在一根总线上挂接多个DS18B20。
DS18B20内部集成了暂存寄存器(或称为暂存RAM)和EEPROM两类存储器。
暂存RAM为9个字节,其地址分配及其相关说明如表1所示。
单片机通过命令实现对DS18B20的控制,其支持的主要命令如表2所示。
DS18B20的复位操作、读写操作都必须遵从严格的时序,其复位时序、读写时序分别如图3和图4所示。
关于DS18B20的详细介绍和使用方法可以参考其数据手册。
表1DS18B20暂存RAM地址分配及其说明
寄存器名称
地址
说明
温度低字节
0
温度测量值的低8位,即b7b6b5b4b3b2b1b0
温度高字节
1
温度测量值的高3位及符号位,即SSSSSb10b9b8
温度高限
2
温度报警上限,也可以用作自定义字节
温度高限
3
温度报警下限,也可以用作自定义字节
配置寄存器
4
格式为0R1R011111,R1和R0为00、01、10、11对应的分辨率分别为9、10、11和12位(包括符号位)
保留
5
未定义
保留
6
未定义
保留
7
未定义
校验码
8
按X8+X5+X4+1对前8个字节进行CRC校验
表2DS18B20主要命令及其功能说明
命令码
功能说明
命令码
功能说明
33H
读ROM中的64位地址序列码
BEH
读9字节暂存寄存器
55H
只有地址码匹配的DS18B2才能接受后续的命令
4EH
写入温度上/下限,紧随其后是2字节数据,对应上限和下限值
F0H
锁定总线上DS18B20的个数和识别其ROM中的64位地址序列码
48H
将9字节暂存寄存器的第3和4字节复制到EEPROM中
ECH
只有温度超过上限或下限的DS18B20才做出响应
B8H
将EEPROM的内容恢复到暂存寄存器的第3和4字节
44H
启动DS18B20进行温度转换,结果存入9字节的暂存寄存器
B4H
读供电模式,寄生供电时DS18B20发送0,外接电源时DS18B20发送1
CCH
忽略地址序列码,适合单片DS18B20
说
图5系统原理图
3、软件设计
1、软件模块的划分
该系统的控制软件可以分为单片机初始化程序、定时中断服务程序和DS18B20接口程序等模块。
单片机初始化程序由主函数实现,主要完成定时器T0、T1的初始化、中断系统的初始化等功能。
定时器T0中断函数每隔5ms执行1次,动态显示1位数码管;定时器T1中断函数每隔50ms中断1次,每中断20次(1秒)即读取1路DS18B20的温度代码,转换为温度值,再拆分成单个数码后送入显示缓冲区。
DS18B20接口程序主要由复位函数、读位函数、读字节函数、写位函数、写字节函数、读温度函数等组成。
2、参考程序
#include
#include
sbitled0=P3^4;//P3.4~P3.7用作4位LED的位选线
sbitled1=P3^5;
sbitled2=P3^6;
sbitled3=P3^7;
sbitDQ=P2^4;//P2.4用作DS18B20的数据线DQ
floatdataTMP[2]={0,0};//读取后的2个温度值,将其除以2即可得出实际温度;
unsignedchardataf[2]={0,0};//结果是否为负温,"0"为正温,"1"为负温。
unsignedchardatadisp_buf[4]={0,0,0,0};//4位数码管对应的值放入该缓冲区
unsignedchardatadot_position=0;
unsignedchardatachno=0;//对应某路DS18B20
//存各路DS18B20的地址序列号,为便于调试,只设计了2路,可以扩充到8路或更多
unsignedcharcodeSN[2][8]={{16,62,148,60,0,0,0,247},{16,229,146,60,0,0,0,87}};
//数字0~9和通道提示符A~H的段码
unsignedcharcodeseg_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71,0x6f,0x76};
unsignedcharcodeCH[]={10,11,12,13,14,15,16,17};//通道提示符的段码偏移量
//将0.00~999之间的浮点数转为单个数码,并送显示缓冲区和返回小数点的位置
voidftochar(floatvalp)
{
if(valp<10.0)
{
dot_position=1;
valp*=100.0;
}
elseif((valp>=10.0)&&(valp<100.0))
{
dot_position=2;
valp*=10.0;
}
elseif((valp>=100.0)&&(valp<1000.0))dot_position=3;
disp_buf[1]=(int)valp/100;
disp_buf[2]=((int)valp%100)/10;
disp_buf[3]=((int)valp%100)%10;
}
//延时15微妙的函数
voiddelay(unsignedcharn)
{
do{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//_nop_()的头文件为intrins.h
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
n--;
}while(n);
}
//DS18B20复位函数,按复位时序进行设计
voidow_reset(void)
{
DQ=0;//DQ置为低电平
delay(36);//保持480μs
DQ=1;//DQ置为高电平
delay(24);//延时,等DS18B20输出低电平
}
//DS18B20读位函数,按读位时序进行设计
unsignedcharread_bit(void)
{
unsignedchari;
DQ=0;//DQ置为低电平
DQ=1;//DQ置为高电平
for