DS18B20温度传感器简介和1-Wire驱动程序

DS18B20简介

DS18B20数字温度计提供9位到12位摄氏温度测量,并具有非易失性用户可编程上、下触发点报警功能。

DS18B20通过一根单线总线与中央微处理器通信,根据定义,该总线只需要一条数据线(和地)。它的工作温度范围为-55°C到+125°C,在范围- 10°C到+85°C上精确到±0.5°C。
此外,DS18B20可以直接从数据线获得电源(“寄生电源”),消除了外部电源的需求。

每个DS18B20都有一个独特的64位串行代码,它允许多个DS18B20在同一根单线总线上工作。因此,使用一个微处理器来控制分布在大范围内的多个DS18B20s是很简单的。受益于此功能的应用包括暖通空调环境控制,建筑内的温度监测系统,设备,或机械,过程监测和控制系统。

管脚定义:
在这里插入图片描述
内部结构:
在这里插入图片描述

特性:

  • 独特的1-Wire总线接口仅需要一个管脚来通信(不包含地线)。
  • 每个设备的内部ROM上都烧写了一个独一无二的64位序列号。
  • 多路采集能力使得分布式温度采集应用更加简单。
  • 无需外围元件。
  • 能够采用数据线供电,供电范围为3.0V至5.5V。
  • 温度可测量范围为:-55℃至+125℃(-67℉至+257℉)。
  • 温度范围-10℃至85℃时测温分辨率0.5℃。
  • 内部温度采集精度可以由用户自定义为9-Bits至12-Bits。
  • 温度转换时间在转换精度为12-Bits时达到最大值750ms。
  • 用户自定义非易失性的的温度报警设置。
  • 定义了温度报警搜索命令和当温度超过用户自定义的设定值时。
  • 可选择的8-Pin SO (150 mils), 8-Pin μSOP,及3-Pin TO-92封装。
  • 与DS1822程序兼容。
  • 应用于温度控制系统,工业系统,民用产品,温度传感器,或者任何温度检测系统中。

DS18B20的两种供电方式

DS18B20可以通过VDD引脚由外部供电,或者可以由“寄生电源”供电,这使得DS18B20可以不采用当地的外部电源供电而实现其功能。

外部电源供电方式具有不需要上拉的MOSFET、该1-Wire总线在温度转换期间可执行其他动作的优点,外部电源供电方式如下图所示:

在这里插入图片描述
“寄生电源”供电方式在远程温度检测或空间比较有限制的地方有很大的应用,其由DQ口拉高时向其供电。总线拉高的时候为内部电容(Cpp)充电,当总线拉低是由该电容向设备供电。当DS18B20为“寄生电源”供电模式时,该VDD引脚必须连接到地。“寄生电源”供电方式在温度超过+100℃时不推荐使用,因为在超过该温度下时将会有很大的漏电流导致不能进行正常的通信。实际应用中,在类似的温度状态下强烈推荐该DS18B20由外部电源供电,“寄生电源”供电方式如下图所示。
在这里插入图片描述

64位ROM

每个DS18B20包含一个唯一的64位代码(见下图)存储在ROM中。ROM代码的最低有效位8位包含DS18B20的家族代码:28h。接下来的48位包含一个唯一的序列号。高8位包含一个循环冗余校验(CRC)字节(CRC=X8+X5+X4+1),它是从ROM代码的前56位计算出来的。64位ROM代码和相关的ROM功能控制逻辑允许DS18B20在1线总线系统上有多个器件同时工作。

在这里插入图片描述

温度传感器

DS18B20的核心功能是直接温度—数字测量,上电后工作在低功耗闲置状态下,其温度转换可由用户自定义为9、10、11、12位精度分别为0.5℃、0.25℃、0.125℃、0.0625℃分辨率,上电默认为12位转换精度。温度数据以一个16位标志扩展二进制补码数的形式存储在温度寄存器中,符号标志位(S)温度的正负极性:正数则S=0,负数则S=1。如果DS18B20被定义为12位的转换精度,温度寄存器中的所有位都将包含有效数据。若为11位转换精度,则BIT 0为未定义的。若为10位转换精度,则BIT 1和BIT 0为未定义的。 若为9位转换精度,则BIT 2、BIT 1和BIT 0为未定义的。下表为在12位转换精度下温度输出数据与相对应温度之间的关系表。
在这里插入图片描述
温度/数据对应关系如下表所示:
在这里插入图片描述
例如,+125℃的数值为 0X07D0H,计算方法:
0X07D0H 》二进制 00000 0111 1101 0000 》十进制 2000 》温度=0.0625*2000=125℃。
例如,-55℃的数值为 FC90H,计算方法是:
FC90H 》二进制 1111 1100 1001 0000 》取反后 0000 0011 0110 1111 》加 1 后为 0000 0011
0111 0000 》十进制 880 》温度=0.0625*880=-55℃。

1-Wire Bus简介

单总线(1-Wire Bus),即只有一根线,是由美国 DALLAS 半导体公司推出的扩展总线技术,和 SPI、I2C 不同的是,单总线只有一根信号线(地线除外),整个通信过程的数据交换和控制都由这根线完成,可以说单总线既作为时钟线,又作为数据线,数据在单总线上传输是双向的。

采用单总线的好处是:节省 IO 资源、硬件开销小、资源结构简单、易于控制、易于扩展以及后期维护、成本低等,单总线结构具有简洁且经济的特点,可使用户轻松地组建传感器网络,从而为测量系统的构建引入全新的概念。

挂在单总线上的器件我们称为单总线器件,目前,常见的单总线器件主要有:数字温度传感器(如 DS18B20 和 DS1821)、门禁、身份识别器(如 DS1990A)、A/D 转换器(如 DS2450)等。

单总线的主要特点如下:
①、只有一根线;
②、传输速度一般是 16.3Kbit/s,最大可达 142Kbit/s;
③、只有一个单主机(可以是微控制器),可以是一个或多个从机,所挂的从机数量几乎不受限制;
④、总线空闲时为高电平,数据传输是双向的;
⑤、总线是分时工作的,同一个时刻只能和一个从机进行通信;
⑥、连接到单总线的每个器件必须具有漏极开路或三态输出;
⑦、总线上的信号,除了应答脉冲外,其它都是由主机发出同步信号,并且发出的所有命令和数据字节的低位在前。

在这里插入图片描述
设备(主机或者从机)通过漏极开路或者三态端口接到单总线上,当设备不发送数据时释放总线,以便总线给其它设备使用。由于是漏极开路,需要在电路中加一个上拉电阻,所以,当单总线为空闲状态时,总线状态为高电平。
不管什么原因,如果传输过程需要暂时挂起,且要求传输过程还能够继续的话,则总线必须处于空闲状态。位传输之间的恢复时间没有限制,只要总线在恢复期间处于空闲状态(高电平)。
如果总线保持低电平超过 480us,总线上的所有器件将复位。

DS18B20通信时序

DS18B20每次操作都分为三个步骤:
1、初始化
2、ROM相关命令(后续包含任何数据交换的操作)
3、功能相关命令(后续包含任何数据交换的操作)

每次访问DS18B20时遵循这个顺序是非常重要的,因为DS18B20在序列中的任何步骤丢失或无序时都不会响应。这个规则的例外是命令Search ROM [FOh]和Alarm Search [ECh]命令。在发出这两个ROM命令中的任何一个之后,master必须返回到步骤1再次开始。
这个后续包含任何数据交换的操作含义就是,比如你发出了一个读ROM的命令,那么接下来DS18B20就会将ROM码发给你,类似这种。如果在操作完ROM后不需要操作功能相关命令,那么下次就直接从初始化开始即可。

初始化

所有事件都以初始化序列开始。初始化序列由主机发送的复位脉冲和由DS18B20从机发送的存在脉冲组成。存在脉冲让主机知道从属设备(如DS18B20)在总线上并且准备好操作。

ROM相关命令(后续包含任何数据交换的操作)

主机检测到DS18B20发出的存在脉冲后,它可以发出一个ROM命令。这些命令在每个从设备的唯一64位ROM代码上操作,并允许主设备单独挑选出一个特定的设备,如果许多设备存在于单线总线上。这些命令还允许主机确定总线上存在多少和什么类型的设备,或者是否有任何设备经历了警报状态。ROM命令共有5条,每条命令长度为8位。在发出DS18B20功能命令之前,主设备必须发出一个适当的ROM命令。ROM命令的操作流程图如图11所示。

搜索 ROM [F0h]
当一个系统最初通电时,主机必须识别总线上所有从设备的ROM代码,这允许主机决定从设备的数量和它们的设备类型。这个过程要求主机执行一个搜索ROM循环(即,搜索ROM命令之后进行数据交换),尽可能多的次数来识别所有的从设备。如果在总线上只有一个从机,更简单的Read ROM命令可以用来代替搜索ROM进程。关于搜索ROM程序的详细说明,请参阅

读 ROM [33h]
此命令只能在总线上有一个从机时使用。它允许总线主机读从机的64位ROM代码而不使用搜索ROM过程。如果在总线上有多个从机时使用这个命令,那么当所有从服务器试图同时响应时,就会发生数据冲突。

匹配 ROM [55h]
匹配ROM命令后跟一个64位ROM代码序列允许总线主机在一个多点或单点总线上给一个特定的从设备寻址。只有与64位ROM代码序列完全匹配的从机才会响应主机发出的功能函数命令;总线上的所有其他从机将等待复位脉冲。

跳过 ROM [CCh]
主机可以使用这个命令来同时寻址总线上的所有设备,而不需要发送任何ROM代码信息。例如,主机可以通过发出Skip ROM命令,然后是Convert T [44h]命令,使总线上的所有DS18B20同时执行温度转换。注意,只有在总线上有一个从设备时,Read Scratchpad [BEh]命令才能跟随Skip ROM命令。在这种情况下,允许主机从从机读取而不发送设备的64位ROM代码可以节省时间。如果有多个从站,因为多个设备将尝试同时传输数据,一个跳过ROM命令后跟一个Read Scratchpad命令将导致总线上的数据碰撞。

告警搜索 [ECh]
该命令的操作与Search ROM命令的操作相同,只是只有设置了报警标志的从机才会响应。这个命令允许主设备确定在最近的温度转换期间是否有任何DS18B20经历了告警状态。在每个警报搜索周期之后(即,警报搜索命令之后是数据交换),总线主机必须返回到事务序列中的第1步(初始化)。

功能相关命令(后续包含任何数据交换的操作)

总线主机使用ROM命令来寻址它希望与之通信的ds18b20后,主机可以发出DS18B20功能命令之一。这些命令允许主机对DS18B20的scratchpad存储器进行读写,启动温度转换并确定电源模式。

温度转换 [44h]
该命令启动单个温度转换。转换之后,产生的热数据被存储在scratchpad内存中的2字节温度寄存器中,DS18B20返回到它的低功耗空闲状态。如果设备在寄生电源模式下使用,在这个命令发出后的10us (max)内,主机必须在转换(tcoNy)的持续时间内在为DS18B20供电部分中描述的1线总线上启用一个强上拉。如果DS18B20由外部电源供电,主机可以在转换T命令后发出读时隙,DS18B20将响应通过发送一个0,温度转换正在进行,转换完成时一个1。在寄生功率模式下,这种通知技术不能被使用,因为总线在转换期间被强上拉拉得很高。

写缓冲器 [4Eh]
这个命令允许主机将3字节的数据写入DS18B20的scratchpad。第一个数据字节被写入 TH ,第二个字节被写入TL ,第三个字节被写入配置寄存器(第4字节)。数据必须首先被传输最低有效位。在主机发出重置之前,所有三个字节都必须被写入,否则数据可能被损坏。

读缓冲器 [BEh]
这个命令允许主机读取scratchpad的内容。数据传输从字节0的最低有效位开始,直到第9个字节(字节8 CRC)被读取。如果只需要scratchpad数据的一部分,master可以在任何时候发出复位来终止读取。

复制缓冲器 [48h]
这个命令将scratchpad,TH、TL和配置寄存器(字节2、3和4)的内容复制到EEPROM。如果设备在寄生电源模式下使用,在这个命令发出后的10us (max)内,主机必须在单线总线上启用一个强上拉,至少10ms.

重调缓冲器 [B8h]
该命令从EEPROM中召回告警触发器值(TH和T)和配置数据,并将数据分别以字节2、3和4的形式放置在scratchpad中。DS18B20将通过在召回进行时发送0,在召回完成时发送1来指示召回的状态。召回操作在设备上电时自动发生,因此只要设备上电,有效的数据就可以在scratchpad中获得。

读供电 [B4h]
主设备发出这个命令,后面跟着一个读时隙来确定总线上是否有任何ds18b20s正在使用寄生电源。在读取时隙期间,寄生供电的DS18B20s将把总线拉低,外部供电的DS18B20s将让总线保持高电平。

单个DS18B20读取温度值驱动

第1步:配置GPIO,连接数据线的IO配置为输出即可,不同芯片平台的代码不同不做具体代码展示,所以IO口的方向(输入、输出)在读、写过程中是不断变化的

uint8_t DS18B20_Init(void)
{
    
    
  //开启GPIO时钟
 
  //端口初始化为推挽输出模式
 
  //默认置高电平
  
  ds18b20_reset();  /* 复位DS18B20 */
  return ds18b20_check(); /* 返回DS18B20应答结果,这里可以判断DS18B20是否存在 */
}

第2步:配置延时,可以用软件延时,也可用硬件定时器延时,建议在示波器下校验一下精准度,不同芯片平台的代码不同也不做具体展示

void delay_us(uint32_t num)
{
    
    

}

第3步:初始化以及检测DS18B20是否存在

所有与DS18B20的通信都以一个初始化序列开始,该序列由一个来自主机的复位脉冲和一个来自DS18B20的存在脉冲组成。
如下图所示。当DS18B20发送存在脉冲来响应复位时,它向主机指示它在总线上并且准备好操作。

  • 在初始化序列期间,总线主发送(Tx)复位脉冲通过拉低1线总线至少480us。
  • 总线主机然后释放总线并进入接收模式(Rx)。
  • 当总线被释放时,5K电阻拉高总线。当DS18B20检测到上升边缘时,等待15μus到60μs,然后DS18B20通过拉低总线60us到240us发送存在脉冲。

在这里插入图片描述

初始化时序代码如下所示:

//复位DS18B20
void DS18B20_Rst(void)	   
{
    
           
    DS18B20_IO_OUT();  //SET DQ OUTPUT
    DS18B20_DQ_0();    //拉低DQ
    delay_us(750);     //拉低750us
    DS18B20_DQ_1();    //DQ=1 
    delay_us(15);      //15US
}
 
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
uint8_t DS18B20_Check(void) 	   
{
    
       
	uint8_t retry=0;
	DS18B20_IO_IN();
	// 等待应答脉冲(一个60~240us的低电平信号 )的到来
	// 注意:从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
	while (DS18B20_DQ_READ()&&retry<100)//< 最多200us
	{
    
    
		retry++;
		delay_us(2);//每次等待2us
	};	 
	if(retry>=100) return 1;
	else retry=0;
	// 有应答脉冲,且存在时间不超过240us
	while (!DS18B20_DQ_READ()&&retry<120)//< 最多240us
	{
    
    
		retry++;
		delay_us(2);//每次等待2us
	};
	if(retry>=120)return 1;	    
	return 0;
}

示波器下时序效果展示:
在这里插入图片描述

第4步:开始转换DS18B20,写入ROM命令:0XCC和0X44。

有两种写时隙:“写1”时隙和“写0”时隙。总线用一个写1时隙写一个逻辑1到DS18B20和一个写0时隙写一个逻辑0到DS18B20。所有写槽的持续时间必须小于60us,每个写槽之间必须有逻辑单元恢复的时间间隔。

  • 这两种写时隙都是由主机拉低单线总线来启动的(见下图)。
  • 为了产生一个写1时隙,在将1线总线拉低后,总线主必须在15us内释放1线总线。当母线被释放时,5k上拉电阻将母线拉高。
  • 为了产生写0时隙,在拉低总线后,总线主必须在时隙期间(至少60us)继续保持总线低电平。
  • DS18B20在一个窗口期间对单线总线进行采样,这个窗口在主机启动写时隙后持续15us到60us。如果总线在采样窗口期间是高电平,一个1被写入DS18B20,如果线路是低电平,一个0被写入DS18B20。
  • 两次独立的写时隙之间至少需要 1us 的恢复时间(图中的 t REC )

在这里插入图片描述
代码如下:

//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(uint8_t dat)     
{
    
                 
    uint8_t j;
    uint8_t testb;
    DS18B20_IO_OUT();	//SET DQ OUTPUT;
    for (j=1;j<=8;j++) 
    {
    
    
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
    
    
            DS18B20_DQ_0();	// Write 1
            delay_us(2);                            
            DS18B20_DQ_1();
            delay_us(60);             
        }
        else 
        {
    
    
            DS18B20_DQ_0();	// Write 0
            delay_us(60);             
            DS18B20_DQ_1();
            delay_us(2);                          
        }
    }
}
 
//开始温度转换
uint8_t DS18B20_Start(void) 
{
    
    
    DS18B20_Rst();
    if(!DS18B20_Check())
    {
    
    
        DS18B20_Write_Byte(0xcc);	// skip rom
        DS18B20_Write_Byte(0x44);	// convert
        return 0;
    }
    else
    {
    
    
        return 1;
    }
}

示波器下时序效果展示:
在这里插入图片描述

第5步: 写入读取DS18B20暂存器功能命令:0XCC和0XBE
示波器下时序效果展示:
在这里插入图片描述

第6步: 读取温度寄存器数据,这里只需要读取两个字节(16位)即可。
当主机将数据线从逻辑高电平拉到逻辑低电平时,启动读取时隙。当主机把总线拉低时,数据线必须保持在低逻辑电平至少 1µ 后释放,必须在 15 us 内读取数据。所有读取时隙的持续时间必须至少为 60µs。两次独立的读时隙之间至少需要 1us 的恢复时间(图中的 t REC ):
在这里插入图片描述

//从DS18B20读取一个位
//返回值:1/0
uint8_t DS18B20_Read_Bit(void) 	 
{
    
    
    uint8_t data;
    DS18B20_IO_OUT();	//SET DQ OUTPUT
    DS18B20_DQ_0(); // 读时间的起始:必须由主机产生 >1us <15us 的低电平信号
    delay_us(2);
    DS18B20_DQ_1(); 
    DS18B20_IO_IN();	//SET DQ INPUT 设置成输入,释放总线
    delay_us(12);
    if(DS18B20_DQ_READ()) data=1;
    else data=0;
    delay_us(50);
    return data;
}
 
//从DS18B20读取一个字节
//返回值:读到的数据
uint8_t DS18B20_Read_Byte(void)     
{
    
            
    uint8_t i = 0,j = 0,dat = 0;
    for (i=1;i<=8;i++) 
    {
    
    
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }
    return dat;
}

示波器下时序效果展示:

在这里插入图片描述

第7步:将十六进制数据转换为十进制形式

float DS18B20_Read_Temp(void)
{
    
    
    uint8_t temp_flag;
    float temp;
    uint8_t TL,TH;
    uint16_t tem;

    DS18B20_Write_Byte(0xcc);	// skip rom
    DS18B20_Write_Byte(0xbe);	// convert	    
    TL=DS18B20_Read_Byte(); 	// LSB   
    TH=DS18B20_Read_Byte(); 	// MSB  
	    	  
    tem = ((uint16_t)TH << 8) | (uint16_t)TL;
    if(TH>7)
    {
    
    
        tem = (~tem) + 1;
        temp_flag=0;			//温度为负  
    }
    else
    {
    
    
        temp_flag=1;			//温度为正	  	  
    }
    temp=(float)tem/16.0;		//转换     
    if(temp_flag)return temp; 	//返回温度值
    return -temp;
}
float DS18B20_Get_Temp(void)
{
    
    
    float fget_temp;
    uint8_t check_flag;
    check_flag = DS18B20_Start();
    if(!check_flag)
    {
    
    
        DS18B20_Rst();
        DS18B20_Check();
        fget_temp = DS18B20_Read_Temp();
        printf("DS18B20_Get_temp = %f\r\n", fget_temp);
        return fget_temp;
    }
    printf("DS18B20_Get_temp fail\r\n");
    return 1;
}

二进制:110010100按照数据手册转换为十进制404,404除以16为25.25

多个DS18B20读取温度值驱动

待更。。。

推荐阅读:

https://blog.csdn.net/qq_37429313/article/details/114339725

https://blog.csdn.net/m0_38106923/article/details/104530051

https://britripe.blog.csdn.net/article/details/116858834

https://www.bbsmax.com/A/QV5ZPZK2zy/ 读多个ds18b20

https://wenku.baidu.com/view/9a4108d38462caaedd3383c4bb4cf7ec4bfeb64e.html?wkts=1678781954274&bdQuery=%E8%AF%BB%E5%A4%9A%E4%B8%AAds18b20

https://blog.51cto.com/u_15046463/5889109 原子

猜你喜欢

转载自blog.csdn.net/weixin_44788542/article/details/129641281