DS18B20 是美信公司的一款温度传感器,单片机可以通过 1-Wire 协议与 DS18B20 进行通信,最终将温度读出。1-Wire 总线的硬件接口很简单,只需要把 DS18B20 的数据引脚和单片机的一个 IO 口接上就可以了。硬件的简单,随之而来的,就是软件时序的复杂。该温度传感器对时间的精确要求较高。我们所需要用到的功能不多……
DS18B20主要由4部分组成:64 位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。64位ROM的排的循环冗余校验码(CRC=X8+X5+X^4+1)。 ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的(单片机不需要进行ROM匹配)。
DS18B20采集完温度后,数据以2个字节的形式储存在寄存器中,其中S为符号位
下面是工作时序,根据蓝桥杯的驱动代码进行分析
首先是初始化
1-Wire 总线开始前需要检测这条总线上是否存在 DS18B20这个器件。如果这条总线上存在 DS18B20,总线会根据时序要求返回一个低电平脉冲,如果不存在的话,也就不会返回脉冲,即总线保持为高电平,所以习惯上称之为检测存在脉冲。此外,获取存在脉冲不仅仅是检测是否存在 DS18B20,还要通过这个脉冲过程通知 DS18B20准备好,单片机要对它进行操作了。
实粗线是我们的单片机 IO 口拉低这个引脚,虚粗线是 DS18B20 拉低这个引脚,细线是单片机和 DS18B20 释放总线后,依靠上拉电阻的作用把 IO 口引脚拉上去。51 单片机释放总线就是给高电平。
具体操作时序为:单片机拉低IO口-----单片机拉高-----检测IO口是否有低电平返回
然后就是注意时间了……
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
EA=0; //最好将中断关闭
DQ = 1; //DQ为芯片与单片机相连的IO口
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
EA=1;
return initflag;
}
下面是写和读的操作
首先是写
写0的话,单片机直接拉低就可以了,DS18B20 会在从 15us 到 60us 之间的时间来读取这一位。
写1的话,单片机需要先拉低,拉低时间需大于1us,然后再拉高,DS18B20 会在从 15us到 60us 之间的时间来读取这一位。
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
EA=0;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01; //从低位开始写
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
EA=1;
}
然后是读
当要读取 DS18B20 的数据的时候,我们的单片机首先要拉低这个引脚,并且至少保持1us 的时间,然后释放引脚,释放完毕后要尽快读取。
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
EA=0;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1; //先接受低位
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
EA=1;
return dat;
}
最后便是操作的DS18B20的一些指令:
跳过ROM匹配:
启动温度转换:
读取温度(注意先读到的是低字节的数据)
(针对蓝桥杯的驱动的修改……)
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--)
{
for(i=0;i<8;i++); //新加,延时8倍
}
}
在读取温度时的具体操作如下
(1)初始化
(2)跳过ROM匹配
(3)发送温度转换指令
(4)初始化
(5)跳过ROM匹配
(6)发送读取温度指令
(7)依次读取DS18B20发出的从第0一第8,共九个字节的数据。如果只想读取温度数据,那在读完第0和第1个数据后就不再理会后面DS18B20发出的数据即可。
代码如下:
//读取温度的集体操作
void ReadTemp_DS18B20()
{
uchar TH,TL;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
TL=Read_DS18B20();
TH=Read_DS18B20();
Temp=(TH<<4)|(TL>>4);
}
经实验,可以读取温度值
Reference:
https://blog.csdn.net/FunkyFrog821951259/article/details/56479880
http://bbs.21ic.com/icview-2478740-1-1.html
DS18B20datasheet