毕业设计常用温度测量模块之DS18B20温度传感器介绍

DS18B20介绍

DS18B20是一种单总线数字温度传感器,测试温度范围-55℃-125℃,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。单总线通信,意味着没有时钟线,只有一根通信线。单总线读写数据是靠控制起始时间和采样时间来完成,所以时序要求很严格,这也是DS18B20驱动编程的难点。

DS18B20引脚

三根线:
两个引脚一个是电源一个是低
在这里插入图片描述

典型原理图

在这里插入图片描述

在这里插入图片描述
64 位ROM。它的内容是64 位序列号,它可以被看作是该DS18B20 的地址序列码,其作用是使每个DS18B20 都各不相同,这样就可以实现一根总线上挂接多个DS18B20 的目的。这个就是传感器的身份证号码

64位的数居组成类型
在这里插入图片描述

暂存器结构

在这里插入图片描述
以上是内部9 个字节的暂存单元。
byte0~byte1 是温度存储器,用来存储转换好的温度。
Byte1是高位,Byte0是低位:图中例子是

字节2~3 是用户用来设置最高报警和最低报警值。这个可以用软件来实现。
设置门限值

字节4 是配置寄存器,用来配置转换精度,让它工作在9~12 位。
调节精度

字节5~7 保留位。【0xFF 0x0C 0x10】

字节8 CRC校验位。是64位ROM中的前56位编码的校验码。由CRC发生器产生。

温度数据的格式

在这里插入图片描述
温度寄存器由两个字节组成,分为低8位和高8位。一共16位。
其中,第0位到第3位,存储的是温度值的小数部分

第4位到第10位存储的是温度值的整数部分

第11位到第15位为符号位。全0表示是正温度全1表示是负温度

配置寄存器

存储器的第 4 位为配置寄存器,其组织见下图 。用户可以通过按表 3 所示设置 R0和 R1 位来设定 DS18B20 的精度。上电默认设置:R1=1,R0=1(12 位精度)。注意:精度和转换时间之间有直接的关系。暂存器的位 7 和位 0-4 被器件保留,禁止写入;在读回数据时,它们全部表现为逻辑 1
在这里插入图片描述

精度配置跟转换时间对应关系

精度值:
9-bit 0.5℃
10-bit 0.25℃
11-bit 0.125℃
12-bit 0.0625℃
在这里插入图片描述

温度数据对应关系

在这里插入图片描述
注意:如果温度是一个负温度,要将读到的数据减1再取反
因为负数是以补码的形式存储的

温度解析说明

当五个符号位S=0时,温度为正值,直接将后面的11位二进制转换为十进制,再乘以0.0625(12位分辨率),就可以得到温度值;

当五个符号位S=1时,温度为负值,先将后面的11位二进制补码变为原码(符号位不变,数值位取反后加1),再计算十进制值。再乘以0.0625(12位分辨率),就可以得到温度值;

例如:
+125℃的数字输出07D0(00000111 11010000)
 
转换成10进制是2000,对应摄氏度:0.0625x2000=125°C

-55℃的数字输出为 FC90。
  
首先取反,然后+1,转换成原码为:11111011 01101111
数值位转换成10进制是870,对应摄氏度:-0.0625x870=-55°C
————————————————
版权声明:本文为CSDN博主「Z小旋」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/as480133937/article/details/112604303

unsigned int Templ,Temp2,Temperature;  //Templ低八位,Temp2高八位
unsigned char Minus Flag=0;  //负温度标志位

if(Tenp2&0xFC//判断符号位是否为1
{
	Minus Flag=l; //负温度标志位置1
	Temperature=((Temp2<<8)|Temp1); //高八位第八位进行整合
	Temperature=((Temperature)+1); //讲补码转换为原码,求反,补1
	Temperature*=0.0625;//求出十进制
}
else   //温度为正值
{
	Minus Flag=0;  //负温度标志位置0
	Temperature =((Temp2<<8) |Temp1)*0.0625;
}

单总线协议

初始化时序

初始化时序包括:主机发出的复位脉冲和从机发出的应答脉冲。主机通过拉低单总线480-960μs产生复位脉冲;然后由主机释放总线,并进入接收模式。主机释放总线时,会产生一由低电平跳变为高电平的上升沿,单总线器件检测到该上升沿后,延时15~60μs,接着单总线器件通过拉低总线60~240μsμ来产生应答脉冲。主机接收到从机的以应答脉冲后,说明有单总线器件在线,到此初始化完成。然后主机就可以开始对从机进行ROM命令和功能命令操作
在这里插入图片描述

位写入时序

写时序:当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时序开始。有两种写时序:写1的时序和写0时序。所有写时序必须最少持续60us,两个写周期间至少要有1us的恢复时间。
DQ引脚上的电平变低后,DS18B20在一个15us到60us的时间窗口内对DQ引脚采样。如果DQ引脚是高电平,就是写1,如果DQ引脚是低电平,就是写0。
主机要生成一个写1的时间序,必须把数据线拉到低电平然后释放,在写时序开始后的15us内允许数据线拉到高电平。
主机要生成一个写0的时间序,必须把数据线拉到低电平并保持60us。

在这里插入图片描述
在这里插入图片描述
总结
总线在千15us都是拉低,写0是的后半段是低电平,写1的后半段是高电平(释放总线)

位读取时序

读时隙由主机拉低总线电平至少1μs然后再释放总线,读取DS18B20发送过来的1或者0
DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。若要送出1则释放总线为高电平
在这里插入图片描述
注意:所有读时隙必须至少需要60us,且在两次独立的时隙之间至少需要1ps的恢复时间

同时注意:主机只有在发送读暂存器命令(0xBE)或读电源类型命令(0xB4)后,立即生成读时隙指令,DS18B20才能向主机传送数据。 也就是先发读取指令,再发送读时隙

最后一点: 写时序注意是先写命令的低字节,比如写入跳过ROM指令0xCC(11001100),写的顺序是“零、零、壹、壹、零、零、壹、壹”,

读时序时是先读低字节,在读高字节,也就是先读取高速暂存器的第0个字节(温度的低8位),在读取高速暂存器的第1个字节(温度的高8位) 我们正常使用DS18B20读取温度读取两个温度字节即可

参考历程1 51版本【未进行验证】

sbit DQ=P1^0;	//定义DS18b20的管脚

/*****延时子程序*****/
void delay(unsigned int t)
{
	for(;t>0;t--);
}


/*****初始化DS18B20*****/
unsigned char Init_DS18B20(void)
{
  unsigned char x=0;
  DQ = 1;      //DQ复位
  delay(8);    //稍做延时
  DQ = 0;      //单片机将DQ拉低
  delay(80);   //精确延时,大于480us
  DQ = 1;      //拉高总线
  delay(8);
  x = DQ;      //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  delay(4);
  return x;
}

/*****读一个字节*****/
unsigned char ReadOneChar(void)
{
  unsigned char i=0;
  unsigned char dat = 0;
  for (i=8;i>0;i--)
  {
    DQ = 0;     // 给脉冲信号
    dat>>=1;
    DQ = 1;     // 给脉冲信号
    if(DQ)
    	dat|=0x80;
	delay(4);
  }
  return(dat);
}

/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    DQ = 0;
    DQ = dat&0x01;
	delay(4);
    DQ = 1;
    dat>>=1;
  }
  delay(4);
}

/*****读取温度*****/
int ReadTemperature(void)
{
  	unsigned char a=0;
  	unsigned char b=0;
  	unsigned int t=0;
  	t=Init_DS18B20();
  	if(t) return Real_temp;
  	WriteOneChar(0xCC);  //跳过读序号列号的操作
  	WriteOneChar(0x44);  //启动温度转换
  	t=Init_DS18B20();
  	if(t) return Real_temp;
  	WriteOneChar(0xCC);  //跳过读序号列号的操作
  	WriteOneChar(0xBE);  //读取温度寄存器
  	a=ReadOneChar();     //读低8位
  	b=ReadOneChar();     //读高8位
  	t=b;
  	t<<=8;
  	t=t|a;
  	if(t<=0||t>0x900) 
	return Real_temp;
	t=t*0.625+0.5;
  	return(t);
}


参考例程2 STM32代码

#include "ds18b20.h"
#include "delay.h"	

//复位DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); 	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 	//拉低DQ
    delay_us(750);    	//拉低750us
    DS18B20_DQ_OUT=1; 	//DQ=1 
	delay_us(15);     	//15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();	//SET PG11 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void) 	 
{
    u8 data;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();	//SET PG11 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)     
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();	//SET PG11 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;	// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;	// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}
//开始温度转换
void DS18B20_Start(void) 
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0x44);	// convert
} 

//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在    	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);	 //使能PORTG口时钟 
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;				//PORTG.11 推挽输出
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOG, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOG,GPIO_Pin_11);    //输出1

	DS18B20_Rst();

	return DS18B20_Check();
}  
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();  			// ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB   
    TH=DS18B20_Read_Byte(); 	// MSB  
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;					//温度为负  
    }else temp=1;				//温度为正	  	  
    tem=TH; 					//获得高八位
    tem<<=8;    
    tem+=TL;					//获得底八位
    tem=(float)tem*0.625;		//转换     
	if(temp)return tem; 		//返回温度值
	else return -tem;    
}

#ifndef __DS18B20_H
#define __DS18B20_H 
#include "sys.h"   

//IO方向设置
#define DS18B20_IO_IN()  {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;}
#define DS18B20_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;}
IO操作函数											   
#define	DS18B20_DQ_OUT PGout(11) //数据端口	PA0 
#define	DS18B20_DQ_IN  PGin(11)  //数据端口	PA0 
   	
u8 DS18B20_Init(void);//初始化DS18B20
short DS18B20_Get_Temp(void);//获取温度
void DS18B20_Start(void);//开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void);//读出一个字节
u8 DS18B20_Read_Bit(void);//读出一个位
u8 DS18B20_Check(void);//检测是否存在DS18B20
void DS18B20_Rst(void);//复位DS18B20    
#endif

开发板代码验证

在这里插入图片描述
开发板代码进行了稍微修改
在这里插入图片描述

#include "ds18b20.h"
#include "systick.h"	

/*****************************************************
@函数功能: 复位DS18B20
@函数参数:  None
@函数返回值:None
@注意事项: None	
*****************************************************/
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); //SET PG11 OUTPUT
  DS18B20_DQ_OUT_L; //拉低DQ
  sys_tick_us(750);    //拉低750us
  DS18B20_DQ_OUT_H; //DQ=1 
	sys_tick_us(15);     //15US
}

/*****************************************************
@函数功能: 等待DS18B20的回应
@函数参数:  None
@函数返回值:返回0:存在  返回1:未检测到DS18B20的存在
@注意事项: None	
*****************************************************/
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();//SET PG11 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		sys_tick_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		sys_tick_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}

/*****************************************************
@函数功能: 从DS18B20读取一个位
@函数参数:  None
@函数返回值:返回值:1/0
@注意事项: None	
*****************************************************/
u8 DS18B20_Read_Bit(void) 			 // read one bit
{
  u8 data;
	DS18B20_IO_OUT();//SET PG11 OUTPUT
  DS18B20_DQ_OUT_L; 
	sys_tick_us(2);
  DS18B20_DQ_OUT_H; 
	DS18B20_IO_IN();//SET PG11 INPUT
	sys_tick_us(12);
	if(DS18B20_DQ_IN)
		data=1;
  else data=0;	 
  sys_tick_us(50);           
  return data;
}

/*****************************************************
@函数功能:从DS18B20读取一个字节
@函数参数:  None
@函数返回值:读到的数据
@注意事项: None	
*****************************************************/
u8 DS18B20_Read_Byte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}

/*****************************************************
@函数功能: 写一个字节到DS18B20
@函数参数:  dat 要写入的字节
@函数返回值:None
@注意事项: None	
*****************************************************/
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	  DS18B20_IO_OUT();//SET PG11 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT_L;// Write 1
            sys_tick_us(2);                            
            DS18B20_DQ_OUT_H;
            sys_tick_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT_L;// Write 0
            sys_tick_us(60);             
            DS18B20_DQ_OUT_H;
            sys_tick_us(2);                          
        }
    }
}
/*****************************************************
@函数功能: 开始温度转换
@函数参数:  None
@函数返回值:None
@注意事项: None	
*****************************************************/
void DS18B20_Start(void)// ds1820 start convert
{   						               
    DS18B20_Rst();	   
	  DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
} 
/*****************************************************
@函数功能: 初始化DS18B20的IO口 DQ 同时检测DS的存在
@函数参数:  None
@函数返回值:返回1:不存在 返回0:存在 
@注意事项: None	
*****************************************************/
u8 DS18B20_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟

  //GPIOG9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
 
 	DS18B20_Rst();
	return DS18B20_Check();
}  

/*****************************************************
@函数功能: 从ds18b20得到温度值
@函数参数:  None
@函数返回值:温度值 (-550~1250)
@注意事项: 精度:0.1C	
*****************************************************/
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	  short tem;
    DS18B20_Start ();                    // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert	    
    TL=DS18B20_Read_Byte(); // LSB   
    TH=DS18B20_Read_Byte(); // MSB   
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//温度为负  
    }else temp=1;//温度为正	  	  
    tem=TH; //获得高八位
    tem<<=8;    
    tem+=TL;//获得底八位
    tem=(double)tem*0.625;//转换     
	if(temp)return tem; //返回温度值
	else return -tem;    
}
  • 9
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值