Onewire单总线驱动DS18B20读取温度

前言

基于蓝桥杯单片机,以实战为主,详细解析代码,理解原理。

1.Onewire单总线

1.定义:主机和从机通过1根线进行通信,在一条总线上可挂接的从器件数量几乎不受限制。

2.特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。

3.优点:单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等。

①Onewire单总线通信

1.初始化

初始化过程 = 复位脉冲 + 从机应答脉冲。

主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。

初始化时序图如下所示:
初始化

2.写间隙

写间隙有两种,包括写0的时间隙和写1的时间隙。

当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。

写时间隙时序图如下所示:
写间隙

3.读时间隙
当主机把总线拉低是,并保持至少1 us后释放总线,必须在15 us内读取数据。
读时间隙时序图如下所示:
读间隙

②代码解析

第一步:单总线复位
单总线复位

//DS18B20初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;

  	Delay_OneWire(80); // 延时大于480us
  	DQ = 1;
  	Delay_OneWire(10);  // 14
  	initflag = DQ;     // initflag等于1初始化失败
  	Delay_OneWire(5);
  
  	return initflag;
}

第二步:单总线的写操作
必须连续写八个字,即一个字节;有写0和写1两个操作

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);

}

第三步:单总线的读操作

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
//	unsigned char index = 0;
  	   	
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1; 
	   	Delay_us();

		if(DQ)  
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

单总线延时函数

////单总线延时函数
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

2.DS18B20芯片

DS18B20是常用的数字温度传感器,其输出的是数字信号,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。 DS18B20数字温度传感器接线方便,封装成后可应用于多种场合,如管道式,螺纹式,磁铁吸附式,不锈钢封装式,型号多种多样,有LTM8877,LTM8874等等。

①DS18B20用法

综述
上电后默认为85C。
寄存器
字节3和字节4分别为设置过温警告和过低警告


在EEPROM上的数据断电是不会丢失的

跳过ROM
当只有一个设备的时候,直接跳过ROM寻址,ROM寻址用于多个设备公用,用于判断具体是哪一个芯片

温度转换
让DS18B20开启温度转换模式,且转换结束后会响应1,所以需在代码后面加上while(!DQ)来等待DS18B20的转换

操作实例1

操作实例二(仅包含一个DS18B20):
操作实例2

②代码解析

1:读取温度(仅仅包含整数部分)

unsigned char	temperature()
{
	char temp;
	uchar HI_temp, LOW_temp;
	
	Init_DS18B20();			//DS18B20重置
	Write_DS18B20(0xcc);		//跳过ROM寻址
	Write_DS18B20(0x44);		//设置为温度读取模式 (跳过了对暂存寄存器的写取)
	
	Delay_OneWire(200);		//等待温度读取模式的转换
	
	Init_DS18B20();			//DS18B20重置
	Write_DS18B20(0xcc);		//跳过ROM寻址
	Write_DS18B20(0xbe);		//读取暂存寄存器的内容(先低位,再高位)
	LOW_temp = Read_DS18B20();		
	HI_temp = Read_DS18B20();
	
	temp=high<<4;
	temp|=(low>>4);
	
	return temp;
}

2:读取温度(含小数部分)

float rd_temperature(void)
{
	unsigned char MSH,MSL;
	unsigned int temp;
	float temperature;
  init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0x44);
	
	Delay_OneWire(200);
	while(!DQ);
	
	init_ds18b20();
	Write_DS18B20(0xCC);
	Write_DS18B20(0xBE);
	
	MSL=Read_DS18B20();
	MSH=Read_DS18B20();
	
	temp=(MSH&0x0f);
	temp<<=8;
	temp|= MSL;
	temperature=0.0625*temp;
	
	return temperature*10;	//返回值为真实温度*10;
}

寄存器

猜你喜欢

转载自blog.csdn.net/name_longming/article/details/106529360