DS18B20温度传感器时序图解析(STM32)

网上DS18B20的驱动实现代码一大堆,简简单单的就能够移植成功,获得温度值,但是为什么代码这么写?为什么要延时那么长的时间?不对照手册仔细分析时序图,还真是不明白为什么。

下面我们就来详细剖析一下DS18B20的驱动函数的实现。

DS18B20 简介

DS18B20数字温度传感器是美国DALLAS公司生产的单总线数字温度传感器。其测温范围为-55℃~+125℃(-67℉~+257℉),64位只读存储器的片序列号。从而允许多只DS18B20同时并联在一根单线总线上;

华氏度和摄氏度换算关系:

(华氏度-32)×5÷9=摄氏度

DS18B20可以用一个微控制器的GPIO引脚去控制。器件内部高速暂存器区含有两个字节的温度寄存器,用来存储温度传感器输出的数据。

此外,高速暂存器区还有上下温度报警寄存器(TH和TL),和一个字节的配置寄存器。

配置寄存器允许用户将温度的精度设置为9~12位对应的分辨率为0.5℃、0.25℃、0.125℃、0.0625℃。上电默认为12位转换精度。

  • DS18B20存储器图

实际使用中,当只是为了测温,只需用到字节1,字节2和字节5。应用环境中如果没有强干扰,不是十分严格的话,不做校验也可以。

其中,暂存寄存器中的字节5包含着配置寄存器,配置寄存器内容如下图所示:

用户通过改变上表中R0和R1的值来配置DS18B20的分辨率。上电默认为R0=1及R1=1(12位分辨率)。

  • 温度/数据对应表:

温度转换后,温度转换的值将会保存在暂存存储器的温度寄存器中,并且DS18B20将会恢复到闲置状态。

TH,TL和配置寄存器是EEPROM,存储的数据在器件掉电时不会消失。

DS18B20的另一个功能是可以在没有外部电源供电的情况下工作。当总线处于高电平状态,DQ与上拉电阻连接通过单总线对器件供电。

同时处于高电平状态的总线信号对内部电容(Cpp)充电,在总线处于低电平状态时,该电容提供能量给器件。

这种提供能量的形式被称为“寄生电源”;

寄生电源模式时,VDD引脚必须接地。

  • “寄生电源”供电方式

  • 外部电源供电方式

原理图

外观及封装

  • TO-92封装

  • 防水型不锈钢封装

采用导热性高的密封胶灌封,保证了温度传感器的高灵敏性,极小的温度延迟。

芯片每个引脚均用热缩管隔开,防止短路,内部封胶,防水防潮。

引脚说明红线:VCC绿线:GND黄线:DQ,传感器数据总线

驱动实现

INITIALIZATION TIMING

在初始化序列期间,总线控制器拉低总线并保持至少480us以发送一个复位脉冲,返回释放总线,进入接收状态(等待DS18B20应答)。

总线释放后,单总线由上拉电阻拉到高电平。

当DS18B20探测到I/O引脚上的上升沿后,等待15-60us,然后其以拉低总线60-240us的方式发出存在脉冲。至此,初始化时序完毕。

所以,初始化成功的标志就是能否读到DS18B20这个先低后高的脉冲时序,并且拉低的时间要满足60-240us。

复位DS18B20的代码如下:

//复位DS18B20
void DS18B20_Rst(void)     
{                 
    DS18B20_IO_OUT();       //总线设置为输出模式
    DS18B20_DQ_OUT=0;   //主机拉低总线
    delay_us(750); 
    DS18B20_DQ_OUT=1;   //释放总线,产生的上升沿能被DS18B20检测到
    delay_us(15);               //延时15us之后,等待DS18B20发送的低电平信号到达。
}

//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)      
{   
    u8 retry=0;
    DS18B20_IO_IN();        //总线设置为输入模式 
    
    while (DS18B20_DQ_IN&&retry<200)    //等待拉低总线60-240us的低电平
    {
        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;
}

READ/WRITE TIME SLOT TIMING DIAGRAM

DS18B20的写时序(见下图):

主机在写时隙向DS18B20写入数据,其中分为写”0”时隙,和写”1”时隙。总线主机使用写“1”时间隙向DS18B20写入逻辑1,使用写“0”时间隙向DS18B20写入逻辑0。

所有的写时隙必须有最少60us的持续时间,相邻两个写时隙必须要有最少1us的恢复时间。两种写时隙都通过主机拉低总线产生(见下图)。

为了产生写1时隙,在拉低总线后主机必须在15μs内释放总线。在总线被释放后,由于上拉电阻将总线恢复为高电平。

为了产生写”0”时隙,在拉低总线后主机必须继续拉低总线以满足时隙持续时间的要求(至少60μs)。

在主机产生写时隙后,DS18B20会在其后的15~60us的一个时间段内采样单总线(DQ)。在采样的时间窗口内,如果总线为高电平,主机会向DS18B20写入1;如果总线为低电平,主机会向DS18B20写入0。

综上所述,所有的写时隙必须至少有60us的持续时间。相邻两个写时隙必须要有最少1us的恢复时间。所有的写时隙(写0和写1)都由拉低总线产生。

//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)     
{             
    u8 j;
    u8 testb;  
    DS18B20_IO_OUT();   //设置DQ为输出模式
    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来采集信号 
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}

DS18B20的读时序(见下图):

主机发起读时序时,DS18B20仅被用来传输数据给控制器。因此,总线控制器在发出读指令后必须立刻开始读时序。

所有读时序必须最少60us,包括两个读周期间至少1us的恢复时间。

当总线控制器把数据线从高电平拉到低电平时,读时序开始,数据线必须至少保持1us,然后总线被释放。

DS18B20 通过拉高或拉低总线来传输”1”或”0”。

当传输逻辑”0”结束后,总线将被释放,通过上拉电阻回到上升沿状态。

从DS18B20输出的数据在读时序的下降沿出现后15us 内有效。因此,总线控制器在读时序开始后必须把I/O口设置为输入模式,以读取I/O口状态。

阴影部分为DS18B20释放总线的时刻,总线为空闲状态。

//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void)        // read one bit
{
    u8 data;
  DS18B20_IO_OUT();       //设置总线为输出模式
    DS18B20_DQ_OUT=0;   
  delay_us(2);                //拉低最少1us
    DS18B20_DQ_OUT=1;   //拉低再升高,产生读时序
  DS18B20_IO_IN();        //设置总线为输入模式
  delay_us(12);
  if(DS18B20_DQ_IN)data=1;
    else data=0;   
    delay_us(50);           
    return data;
}

//从DS18B20读取一个字节
//返回值:读到的数据
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的功能命令

  • 获取温度值

要获取温度值,我们需要发送上面功能命令0x44,然后发送读取暂存寄存器命令0xBE,然后我们只需要获得暂存器中的9个字节的前两个字节即可。

要获得DS18B20的温度值,需要按照下表中的顺序依次发送功能命令。

获取温度的具体代码实现如下:

//开始温度转换
void DS18B20_Start(void)// ds18b20 start convert
{                              
    DS18B20_Rst();     
  DS18B20_Check();   
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
}

//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
    short tem;
    DS18B20_Start ();                    // ds18b20 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;    
}

跳过ROM序列号检测命令(0xCCH),对于单片DS18B20在线的系统,该命令允许主机跳过ROM序列号检测而直接对寄存器操作,从而节省时间,对于多片DS18B20在线系统,该命令将引起数据冲突。

如果主机只是对一个DS18B20进行操作,进而不需要读取ROM编码了,只要发送跳过ROM(0xCCH)命令,就可以进行温度转换和读取操作了。

  • 获取DS18B20内部ID序列号

因为咱们总线上只有一个DS18B20设备,所以直接发送0x33指令即可READ ROM。

DS18B20中有一个64位光刻ROM,按说明书说法,开始(最低)8位是产品类型标号,对于DS18B20来说都是(28H),接着的48位是该DS18B20自身的序列号,最后8位是前面56位的循环冗余校验码(CRC=X8+X5+X4+1)。

光刻ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。

读取ROM方法:先复位DS18B20,成功后执行读取ROM命令(33H),然后将这64位以8个字节的方式存入数组。

获取DS18B20内部ID序列号的具体代码实现如下:

DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0x33);
			
for(i = 0; i < 8;i++)
{
    arrDS18B20ID[i] = DS18B20_Read_Byte();
}
			
sprintf((char *)dtbuf,"DS18B20 ID is %02X %02X %02X %02X %02X %02X %02X %02X\r\n", arrDS18B20ID[0], arrDS18B20ID[1], arrDS18B20ID[2], arrDS18B20ID[3], arrDS18B20ID[4], arrDS18B20ID[5], arrDS18B20ID[6], arrDS18B20ID[7]);

printf((u8 *)dtbuf,strlen((char *)dtbuf));

我手里的两个DS18B20得到的结果如下所示:

由上可以看出,首字节都是0x28,即产品类型都是一样的。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 3
收藏 4
关注 64
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧