18B20温度传感器详解

数据传感器DS18B20

 编写原因:.....暂略

特性:

1.      单独的单线接口,只需1个接口引脚即可通信;

2.      不需要外部元件;

3.      可用数据线供电;

4.      不需备份电源;

5.      测量范围从-55°C  ~  +125°C, 增量为0.0625°C;

6.      以12位数字值方式读出温度;

7.      在1s内把温度变换为数字;

 18B20温度传感器详解_第1张图片

知识点:

1.      每个18B20包括唯一的64位长的序号放在ROM中;

开始8位产品类型编码| 接着48位每个器件唯一序号| 最后8位:前56位的CRC

2.      18B20最小单位刻度是0.0625°C, (这里后面解释)

  

DS18B20的控制流程

根据DS18B20的通信协议,DS18B20只能作为从机,而单片机系统作为主机,片机控制DS18B20完成一次温度转换必须经过3个步骤:

1.     初始化;

2.      发送ROM指令;

3.      发送18B20功能指令。

@以上3个流程还有顺序不能颠倒且缺一不可,每次只要发送任何一条ROM指令,这个流程必须从第1再开始才能发送另外的ROM指令;

一,初始化

18B20温度传感器详解_第2张图片

/*
*******************************************************************************
**
**                             GPIO_DQ_Out_Mode(void)
**
**
**	功能描述:设置DQ引脚为开漏输出模式
**
**	参  数  :无
**
**	返回值  :无
**
*******************************************************************************
*/
void GPIO_DQ_Out_Mode(void)
{
    GPIO_InitTypeDef GPIO_InitStructure ;
    
    GPIO_InitStructure.GPIO_Pin = DQ_GPIO_Pin ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD ; //开漏输出
    GPIO_Init(DQ_GPIO ,&GPIO_InitStructure) ;
}

/*
*******************************************************************************
**
**                                GPIO_DQ_Input_Mode(void)
**
**
**	功能描述:设置DQ引脚为浮空输入模式
**
**	参  数  :无
**
**	返回值  :无
**
*******************************************************************************
*/
void GPIO_DQ_Input_Mode(void)
{
    GPIO_InitTypeDef GPIO_InitStructure ;
    
    GPIO_InitStructure.GPIO_Pin = DQ_GPIO_Pin ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ; //浮空输入
    GPIO_Init(DQ_GPIO ,&GPIO_InitStructure) ;
}

/*
*******************************************************************************
**                                  Tx_ResetPulse(void)
**
**
**	功能描述:发送复位脉冲
**
**	参  数  :无
**
**	返回值  :无
**
*******************************************************************************
*/
void Tx_ResetPulse(void)
{
   GPIO_DQ_Out_Mode() ;
	
    DQ_Write_0() ;  //复位脉冲
    Delay_10us(50) ; //至少保持480us
    DQ_Write_1() ;  //加速上升沿速度
    Delay_10us(1) ;
}
/*
*******************************************************************************
**
**                              Rx_PresencePulse(void)
**
**
**	功能描述:接受应答信号
**
**	参  数  :无
**
**	返回值  :无
**
*******************************************************************************
*/
void Rx_PresencePulse(void)
{
    GPIO_DQ_Input_Mode() ;
    while( DQ_ReadBit()) ;  //等待DS18b20应答
    while( DQ_ReadBit() == 0) ; //DS18b20将总线拉低60~240us ,然后总线由上拉电阻拉高
    Delay_10us(30) ;
    GPIO_DQ_Out_Mode() ;    //接受完成,主机重新控制总线
}
/*
*******************************************************************************
**                                 DS18B20_Init(void)
**
**
**	功能描述:初始化DS18b20
**
**	参    数:无
** 
**	返回值  :无
**
*******************************************************************************
*/
void DS18B20_Init(void)
{
    Tx_ResetPulse();
    Rx_PresencePulse(); 
}

Tx_ResetPulse:函数:主机总线发送复位脉冲

PresencePulse函数:主机读取18B20返回的存在脉冲(电平持续60-240us)


二.写时序

18B20温度传感器详解_第3张图片


/*
*******************************************************************************
**
**                      Write_OneByte_ToDS18b20(unsigned char data)
**
**
**	功能描述:写一个字节到DS18b20
**
**	参  数  :无
**
**	返回值  :无
**
*******************************************************************************
*/
void Write_OneByte_ToDS18b20(unsigned char data)
{
    unsigned char i ;
    GPIO_DQ_Out_Mode() ;
    for(i=0 ;i<8 ;i++)
    {
        if(data&0x01)    //低位在前
        {
            //写1
            DQ_Write_0() ; //写时间空隙总是从总线的低电平开始
            Delay_10us(1) ;  //15us内拉高
            DQ_Write_1() ;
            Delay_10us(8) ; //整个写1时隙不低于60us
        }
        else
        {
            //写0
            DQ_Write_0() ;
            Delay_10us(11) ; //保持在60us到120us之间
            DQ_Write_1() ;
            Delay_10us(1) ;
        }
        data >>= 1 ;
    }
}
写1 还是写0 由15-60us 的电平区分,所以 DQ_write_0函数后延时长是写0, DQ_write_1函数后延时长是写1;

且是从低位开始写, 所以写完后 data>>=1 ;


三.读时序

18B20温度传感器详解_第4张图片

/*
*******************************************************************************
**
**                       Read_OneByte_FromDS18b20(void)
**
**
**     功能描述:从DS18b20读一个字节
**
**     参  数  :无
**
**     返回值  :读出的数据
**
*******************************************************************************
*/
unsigned charRead_OneByte_FromDS18b20(void)
{
   unsigned char i ,data = 0 ;
   
   for(i=0 ;i<8 ;i++)
    {
       GPIO_DQ_Out_Mode() ;
       data >>= 1 ;
       DQ_Write_0() ;
       Delay_10us(1) ;
       GPIO_DQ_Input_Mode() ;
       Delay_10us(1) ;
       if(DQ_ReadBit())
       {
           data |= 0x80 ;
       }
       Delay_10us(7) ;   //等待这一位数据完成传输
    }
   GPIO_DQ_Out_Mode() ;
   return data ;
}

四.读取温度值和计算

18B20用12位存储温度值,最高位是符号位,下图是其温度存储方式,负温度S=1,正温度S=0;

如:0550H 是+85°C       0191H:+25.0625°C   FC90H是-55°C

18B20温度传感器详解_第5张图片

/*
***************************************************************************************************
**
**        Read_Temperature(unsigned char *sign , unsigned char *interger , unsigned int *decimal)
**
**
**	功能描述:读取温度信息
**
**	参    数:*sign - 保存符号(零上或零下)
**            *integer - 保存整数部分
**            *decimal - 保存小数部分
**
**	返回值  :无
**
***************************************************************************************************
*/
void Read_Temperature(unsigned char *sign , unsigned char *interger , unsigned int *decimal)
{
    unsigned char a=0;
    unsigned char b=0;  
    unsigned int tmp ;
    
    DS18B20_Init();
    Write_OneByte_ToDS18b20(ROM_Read_Cmd);
  
    DS18B20_Init();
    Write_OneByte_ToDS18b20(ROM_Skip_Cmd);//跳过读序列号操作
    Write_OneByte_ToDS18b20(Convert_T); //启动温度转换
    Delay_ms(780);//等待DS18b20转换完成
    
    DS18B20_Init();
    Write_OneByte_ToDS18b20(ROM_Skip_Cmd);
    Write_OneByte_ToDS18b20(Read_Scratchpad); //读取寄存器内容
    
    a= Read_OneByte_FromDS18b20();     //温度低8位
    b= Read_OneByte_FromDS18b20();     //温度高8位
    
    Tx_ResetPulse();  //中断数据读取
    tmp = (b<<8) | a ;
    if(b & 0xF0)
    {
			*sign = 1 ;              //符号部分
			tmp = ~tmp+1 ;		//二进制数求补 再换成十进制数得到被测温度值
    }
    else 
    {
			*sign = 0 ;
    }
    *interger = (tmp>>4) & 0x00FF;  //整数部分
    *decimal = (tmp & 0x000F) * 625 ; //小数部分 实际上是乘以0.0625最小步进 同时把小数变成非小数显示
}

1.因为上面说过每次只要发送了ROM命令 ,再发其他命令必须重新初始化;

2.将存储器中的二进制数求补后再转换成十进制;


代码和数据手册已上传到我的资源:http://download.csdn.net/detail/yx_l128125/6755749


你可能感兴趣的:(嵌入式,ARM)