DS18B20温度传感器
DS18B20是DALLAS公司的1-Wire(单总线)数字温度计芯片,温度测量范围从-55℃至+125℃。
DS18B20使用方便,单片机和DS18B20仅需连接一条数据线,在寄生供电方式下可以不接电源线,DS18B20工作所需的电源可以从数据线获得。
与传统的温度测量方式不同,DS18B20的温度转换结果可直接从数据线读出,在-10℃至+85℃测量精度可达0.5℃。
鉴于以上优点DS18B20自问世以来就广泛的应用于恒温控制系统,消费类产品,电子温度计以及数字环境监测系统。
基本功能:
数字温度计的基本功能如下:
- AT89C51每间隔1秒向DS18B20发送测量温度指令,并读出当前环境温度;
- 在读出当前环境温度值后,用LCD1602显示温度转换的结果;
DS18B20内部结构图:
DS18B20内部电路原理图:
重要之处:
DS18B20的命令序列及操作时序
1.命令序列
典型的单总线命令序列如下:
第一步:初始化;
第二步:ROM命令;
第三步:功能命令。
每次访问单总线器件,必须严格遵守这个命令序列,如果出现序列混乱,则单总线器件不会响应主机。但是,这个准则对于搜索ROM命令和报警搜索命令列外,在执行两者中任何一条命令之后,主机不能执行其后的功能命令,必须返回至第一步。
(1)初始化
基于单总线上的所有传输过程都是以初始化开始的,初始化过程中由主机发出的复位脉冲和从机响应的应答脉冲组成。应答脉冲使主机知道,总线上有从机设备,且准备就绪。
bit Get18B20Ack()
{
bit ack;
EA = 0; //禁止总中断
IO_18B20 = 0; //产生 500us 复位脉冲
DelayX10us(50);
IO_18B20 = 1;
DelayX10us(6); //延时 60us
ack = IO_18B20; //读取存在脉冲
while(!IO_18B20); //等待存在脉冲结束
EA = 1; //重新使能总中断
return ack;
}
首先单片机要拉低这个引脚,持续大概 480us 到 960us 之间的时间即可,我们的程序中持续了 500us。然后,单片机释放总线,就是给高电平,DS18B20 等待大概 15 到 60us 后,会主动拉低这个引脚大概是 60 到240us,而后 DS18B20 会主动释放总线,这样 IO 口会被上拉电阻自动拉高。
由于 DS18B20 时序要求非常严格,所以在操作时序的时候,为了防止中断干扰总线时序,先关闭总中断。然后第一步,拉低 DS18B20 这个引脚,持续 500us;第二步,延时 60us;第三步,读取存在脉冲,并且等待存在脉冲结束。
(2)ROM命令
总线上可以挂多个器件,通过不同的器件地址来访问不同的器件。同样, 1-Wire 总线也可以挂多个器件,但是它只有一条线,如何区分不同的器件呢?
在每个 DS18B20 内部都有一个唯一的 64 位长的序列号,这个序列号值就存在 DS18B20内部的 ROM 中。开始的 8 位是产品类型编码(DS18B20 是 0x10),接着的 48 位是每个器件唯一的序号,最后的 8 位是 CRC 校验码。 DS18B20 可以引出去很长的线,最长可以到几十米,测不同位置的温度。单片机可以通过和 DS18B20 之间的通信,获取每个传感器所采集到的温度信息,也可以同时给所有的 DS18B20 发送一些指令。这些指令相对来说比较复杂,而且应用很少。
我们这里只讲一条总线上只接一个器件的指令和程序。
Skip ROM(跳过 ROM): 0xCC。当总线上只有一个器件的时候,可以跳过 ROM,不进行 ROM 检测。
(3) RAM 存储器操作指令
Read Scratchpad(读暂存寄存器): 0xBE
DS18B20 的温度数据是 2 个字节,我们读取数据的时候,先读取到的是低字节的低位,读完了第一个字节后,再读高字节的低位,直到两个字节全部读取完毕。
Convert Temperature(启动温度转换): 0x44
当我们发送一个启动温度转换的指令后, DS18B20 开始进行转换。从转换开始到获取温度, DS18B20 是需要时间的,而这个时间长短取决于 DS18B20 的精度。
///
2、 DS18B20 的位读写时序///重点
当要给 DS18B20 写入 0 的时候,单片机直接将引脚拉低,持续时间大于 60us 小于 120us就可以了。图上显示的意思是,单片机先拉低 15us 之后, DS18B20 会在从 15us 到 60us 之间的时间来读取这一位, DS18B20 最早会在 15us 的时刻读取,典型值是在 30us 的时刻读取,最多不会超过60us, DS18B20 必然读取完毕,所以持续时间超过 60us 即可。
当要给 DS18B20 写入 1 的时候,单片机先将这个引脚拉低,拉低时间大于 1us,然后马上释放总线,即拉高引脚,并且持续时间也要大于 60us。和写 0 类似的是, DS18B20 会在15us 到 60us 之间来读取这个 1。可以看出来, DS18B20 的时序比较严格,写的过程中最好不要有中断打断,但是在两个“位”之间的间隔,是大于 1 小于无穷的,那在这个时间段,我们是可以开中断来处理其它程序的。发送即写入一个字节的数据程序如下。
void Write18B20(unsigned char dat)
{
unsigned char mask;
EA = 0; //禁止总中断
for (mask=0x01; mask!=0; mask<<=1) //低位在先,依次移出 8 个 bit
{
IO_18B20 = 0; //产生 2us 低电平脉冲
_nop_();
_nop_();
if ((mask&dat) == 0) //输出该 bit 值
IO_18B20 = 0;
else
IO_18B20 = 1;
DelayX10us(6); //延时 60us
IO_18B20 = 1; //拉高通信引脚
}
EA = 1; //重新使能总中断
}
//
当要读取 DS18B20 的数据的时候,我们的单片机首先要拉低这个引脚,并且至少保持1us 的时间,然后释放引脚,释放完毕后要尽快读取。从拉低这个引脚到读取引脚状态,不能超过 15us。大家从图 16-18 可以看出来,主机采样时间,也就是 MASTER SAMPLES,是在 15us 之内必须完成的,读取一个字节数据的程序如下。
/* 从 DS18B20 读取一个字节,返回值-读到的字节 */
unsigned char Read18B20()
{
unsigned char dat;
unsigned char mask;
EA = 0;
for(mask=0x01; mask!=0; mask<<=1)
{
IO_18B20 = 0;
_nop_();
_nop_();
IO_18B20 = 1;
_nop_();
_nop_();
if(!IO_18B20) //读取通信引脚上的值
dat &= ~mask;
else
dat |= mask;
DelayX10us(6);
}
EA = 1;
return dat;
}
//
//