51单片机DS18B20温度采集实验教程
51单片机DS18B20温度采集实验教程
一. 任务目标
- 学习单总线温度传感器的原理和通信时序;
- 使用51单片机的一个 IO 口模拟单总线时序与温度传感器DS18B20通信,将检测的环境温度读取出来。
二、实验要求
- 写出实验设计的主要原理。
- 使用DS18B20温度传感器、数码管显示检测的温度值,在Proteus和普中开发板实物上完成 DS18B20 的环境温度采集。
- 将上述实验成功的代码在Keil中进行仿真运行,使用虚拟逻辑分析仪显示单片机与DS18B20的DQ数据线连接引脚的波形,分析其“初始化–>写—>读”总线时序,与原理进行对比分析:
- 判断其是否符合技术要求;
- 故意在代码中把时序弄错(改延时delay的延时值),再重新运行之前的实验,看DS18B20是否能正确相应并返回温度。
三、具体实现
3.1 实验原理
DS18B20是由 DALLAS 半导体公司推出的一种的“1-Wire bus(单总线)”接口的温度传感器。与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器。
想要实现正确工作,一方面是数据,另一方面则是时序。
3.1.1 数据处理
数据方面,将数据存储在相应的RAM中,片内有9个字节的高速暂存器RAM单元,9个字节具体分布如下:
片内有9个字节的高速暂存器RAM单元,9个字节具体分布如下:
第1字节和第2字节是经转换所得的温度值,以两字节补码形式存放其中。
第3、4字节分别是由软件写入用户报警的上下限值TH和TL。
第5个字节为配置寄存器,可对其更改DS18B20的测温分辨率,高速暂存器的
第6、7、8字节未用,为全1。
第9字节是前面所有8个字节的CRC码,用来保证正确通信。片内还有1个E2PROM为TH、TL以及配置寄存器的映像。
存好之后,要将数据进行温度转换,以下是温度转换的计算方法:
- 当DS18B20采集的温度为+120℃时,输出十六进制数为0x0780。
=120℃ - 假如当DS18B20采集的温度为-55℃时,输出为0xfc90,由于是补码,则先将11位数据取反加1得0x0370,注意符号位不变,也不参加运算,则
=55℃
注意,负号则需对采集的温度进行判断后,再予以显示。
3.1.2 工作时序
DS18B20的工作时序包括初始化时序、写时序和读时序。
- 初始化
粗黑线为主机。灰色细线为上拉电阻。
首先主机上拉输入,即DQ=1,延时Delay5(1);
之后DQ=0,延时480us~ 960us。
等待存在脉冲的到来,15~60us之后,存在脉冲为1个60到240us的低电平。
如果没来则按超时处理,从机接收到主机的复位脉冲。 - 写时序
DQ=1,1us;
DQ=0,若写入0维持不变,1则延时15us,上拉主线,即DQ=1; - 读时序
DQ=1,延时1us;
释放总线,即DQ=0,读数据,如果上拉电阻,读1位数据。若为0,不用管。
3.2 代码实现
实现步骤分别为:
发送启动信号、写入跳过ROM指令、发送温度转换指令、再次启动信号、写入读取温度寄存器指令,然后读取两个字节的温度数据并计算出温度值。
3.2.1 初始化
当DS18B20工作时,首先按照1-Wire协议发送初始化序列,包括发送复位脉冲和存在脉冲。
void init_ds18b20(void)
{
uchar x=0;
DQ =0;
delay5(120);
DQ =1;
delay5(16);
delay5(80);
}
3.2.2 写入数据
向DS18B20写入一个字节的数据。根据1-Wire协议,写入“1”需要在15微秒内拉低数据线,写入“0”需要拉低60微秒。
void writebyte(uchar dat) //函数功能:写1字节
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ =0;
DQ =dat&0x01; //写"1" 在15µs内拉低
delay5(12); //写"0" 拉低60µs
DQ = 1;
dat>>=1;
delay5(5);
}
}
3.2.3 读数据
从DS18B20读取一个字节的数据。通过发送时钟信号并在15微秒内读取数据线状态来完成每一位的读取。
uchar readbyte(void) //函数功能:读取1字节数据
{
uchar i=0;
uchar date=0;
for (i=8;i>0;i--)
{
DQ =0;
delay5(1);
DQ =1; //15µs内拉释放总线
date>>=1;
if(DQ)
date|=0x80;
delay5(11);
}
return(date);
}
3.2.4 完整代码
主函数:首先调用delay5函数进行延时,然后进入一个无限循环,在循环中不断地调用retemp函数读取温度,并将其显示在数码管上。通过分时控制两个数码管显示温度的十位和个位。
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define out P0
sbit smg1=out^4;
sbit smg2=out^5;
sbit DQ=P3^7;
void delay5(uchar);
void init_ds18b20(void);
uchar readbyte(void);
void writebyte(uchar);
uchar retemp(void);
void main(void)
{
uchar i,temp;
delay5(1000);
while(1)
{
temp=retemp();
for(i=0;i<10;i++) //连续扫描数码管10次
{
out=(temp/10)&0x0f;
smg1=0;
smg2=1;
delay5(1000); //延时5ms
out=(temp%10)&0x0f;
smg1=1;
smg2=0;
delay5(1000); //延时5ms
}
}
}
/*--------------精确延时5us子程序---------*/
void delay5(uchar n)
{
do
{
_nop_();
_nop_();
_nop_();
n--;
}
while(n);
}
/*--------------初始化函数--------------------*/
void init_ds18b20(void)
{
uchar x=0;
DQ =0;
delay5(120);
DQ =1;
delay5(16);
delay5(80);
}
/*--------------读取一字节函数----------------*/
uchar readbyte(void)
{
uchar i=0;
uchar date=0;
for (i=8;i>0;i--)
{
DQ =0;
delay5(1);
DQ =1; //15微秒内拉释放总线
date>>=1;
if(DQ)
date|=0x80;
delay5(11);
}
return(date);
}
/*--------------写一字节函数------------------*/
void writebyte(uchar dat)
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ =0;
DQ =dat&0x01;//写"1" 在15微秒内拉低
delay5(12); //写"0" 拉低60微秒
DQ = 1;
dat>>=1;
delay5(5);
}
}
/*--------------读取温度函数------------------*/
uchar retemp(void)
{
uchar a,b,tt;
uint t;
init_ds18b20();
writebyte(0xCC);
writebyte(0x44);
init_ds18b20();
writebyte(0xCC);
writebyte(0xBE);
a=readbyte();
b=readbyte();
t=b;
t<<=8;
t=t|a;
t= t*0.0625;
return(tt);
}
3.2.5 仿真结果
3.3 时序分析
3.3.1 波形图
经过分析后发现符合符合技术要求。
3.3.2 更改时序
找到初始化函数,更改delay5函数的变量。
结果如下:
我们发现,更改数据后,无法正确相应并返回温度。因此,时序对于DS18B20采集环境是至关重要的。
四、实验总结
通过实验,我们发现时序对于DS18B20采集环境是至关重要的。
当我们觉察到温度采集的滞后时,可以尝试更改delay相关参数。