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为符号位

在这里插入图片描述
下面是工作时序,根据蓝桥杯的驱动代码进行分析
首先是初始化
在这里插入图片描述

要检测这条总线上是否存在 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