1. 首页
  2. 技术文章

STM32F10x学习笔记—DS18B20温度传感器的使用第一篇初始化

  • DS18B20介绍

1.单线接口,1wire总线接口,1个IO可挂多个传感器

2.不需要外围电路,一般情况下需要上拉一个电阻到VCC即可。

3.测量范围从-55℃到125℃,最大分辨率为0.5℃

4.供电我们一般3.3V~5V 的CPU都直接可以使用。

  • 温度的计算

DS18B20内部提供温度为0.5℃分辨率的值。其温度读数是以16bit带有符号位的二进制补码形式进行存储。传感器支持多种精度温度的读取9~12bit,最大支持12bit。由于温度传感器默认为12bit,因此我们以12bit精度来读取,关于怎么转换精度,因为用的比较少,这里就不介绍了,思路就是只需要向DS18B20相应的寄存器的写入对应值即可。温度存储如下图1

STM32F10x学习笔记—DS18B20温度传感器的使用第一篇初始化
图1 DS18B20温度存放方式

从图1中我们看到温度值由LSB和MSB组成,低八位带有小数部分,高八位带有符号位。我们看LSB最低位为1/16,因此2进制的1位代表1/16=0.0625℃。这么就简单了,对于正温度,温度值就是除过符号位的值*0.0625,例如图1中125℃为0000 0111 1101 0000换算成10进制为:2000,那么温度就是2000*0.0625=125;对于负温度,我们知道是按照补码形式存放的那么,我们进行换算成正温度即可。例如-10.125℃的二进制:1111 1111 0101 1110 经过取反加1后为:0000 0000 1010 0010 其十进制为162,温度就是162*0.0625=10.125℃  温度符号单独自己加入即可。

  • 读取温度的过程

对于DS18B20来说,每一次读取温度的流程如下:

DS18B20复位—>ROM操作(匹配ROM or 跳过匹配) —>执行转换命令—>读取温度值—>温度计算和转换。

在复位之前我们先考虑对GPIO的初始化,因为器件时单线通信,1个GPIO既需要输出还需要输入采集,因此我们需要把GPIO设置为多种模式进行调用,首先看GPIO的初始化,

代码如下:

void DS18B20_GPIO_Config(void)
{		
  GPIO_InitTypeDef GPIO_InitStructure;	
  RCC_APB2PeriphClockCmd(DS18B20_GPIO_CLK,ENABLE); 			
  GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure );
  /*默认上拉数据线,释放总线*/
  GPIO_SetBits(DS18B20_GPIO_PORT, DS18B20_GPIO_PIN);
}

其中宏的定义如下:

/************************** DS18B20 连接引脚定义********************************/
#define      DS18B20_GPIO_CLK                       RCC_APB2Periph_GPIOA
#define      DS18B20_GPIO_PORT                      GPIOA
#define      DS18B20_GPIO_PIN                       GPIO_Pin_3
/************************** DS18B20 函数宏定义********************************/
#define      DS18B20_GPIO_L	                            GPIO_ResetBits ( DS18B20_GPIO_PORT, DS18B20_GPIO_PIN ) 
#define      DS18B20_GPIO_H	                            GPIO_SetBits ( DS18B20_GPIO_PORT, DS18B20_GPIO_PIN ) 
#define      DS18B20_GPIO_ReadData	                    GPIO_ReadInputDataBit ( DS18B20_GPIO_PORT, DS18B20_GPIO_PIN )

对于GPIO初始化我们初始化为推完输出模式,因为所有通信都是以主机拉低数据信号开始,也就是需要输出模式。总线为高电平为空闲状态。
GPIO设置为输入模式:

void DS18B20_Mode_IPU(void)
{
   GPIO_InitTypeDef GPIO_InitStructure;
  /*选择要控制的DS18B20_DQ_GPIO_PORT引脚*/	
   GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;
  /*设置引脚模式为浮空输入模式*/ 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	
   /*调用库函数,初始化DS18B20_DQ_GPIO_PORT*/
   GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
}

然后在把GPIO设置成输出状态 用于总线状态转换:

void DS18B20_Mode_Out_PP(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  /*选择要控制的DS18B20_DQ_GPIO_PORT引脚*/															   
  GPIO_InitStructure.GPIO_Pin = DS18B20_GPIO_PIN;	
  /*设置引脚模式为通用推挽输出*/
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
  /*设置引脚速率为50MHz */   
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  /*调用库函数,初始化DS18B20_DQ_GPIO_PORT*/
  GPIO_Init(DS18B20_GPIO_PORT, &GPIO_InitStructure);
}

这样就完成了对GPIO的初始化。有了初始化我们就是看一下器件的复位,手册对器件的复位这么写道,主机发送复位脉冲,接着由从属器件返回存在的应答脉冲(PS,脉冲都是低电平)。具体时序参考手册P18页,这么写道: 主机发送低电平复位信号(拉低信号480us-960us)—>等待15us-60us—>接收从器件返回的低电平应答信号(该应答信号持续60us-240us)。
具体代码如下:

unsigned char DS18B20_Rst(void)
{
 unsigned char	timeout=0; 
 unsigned char	timewait=0;
 	
  DS18B20_Mode_Out_PP();/* 主机设置为推挽输出 */
  DS18B20_GPIO_L;	
  ds18b20_delay(75); /* 主机至少产生480us的低电平复位信号 */
  DS18B20_GPIO_H; /* 主机在产生复位信号后,需将总线拉高 释放总线 */	
  ds18b20_delay(2) ;   	/*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
  /***********开始检测 器件是否存在***************/
  DS18B20_Mode_IPU(); // IO变成输入状态
  do	
   {       
    timeout++;	  //等待15~60us 后从机就会发送低电平 
    ds18b20_delay(1); //我们在100us内 如果没有读取到低电平,跳出循环
   }
  while ((DS18B20_GPIO_ReadData==1) && timeout<100 );

  if (timeout>=100)	//判断等待时间超过100us  说明无响应 返回错误值。
   {
     printf("复位失败,从机无响应");
     return 1;	  
   }
  else	//在100us 检测到低电平
     {    
      while ((DS18B20_GPIO_ReadData==0) && timewait<240)//判断低电平持续时间是否符合时序
           {
            timewait++;
	    ds18b20_delay(1);
            }

        if(timewait<240)  //符合返回正常
          {
	     return 0;		 
    	   }
         else return 1;	   //不符合返回失败
   	}
}

首先设置为输出模式,然后拉低总线,等待480-960us我们这里等待750us,延迟函数1次为10us,具体我们最后会单独说明这个延迟函数,在这里我们知道是延迟多少就行,拉高总线释放总线等待20us后,改为输入状态,开始循环检测是否有返回低电平应答信号,如果循环100次仍未检测到,说明器件无响应,反之,我们在持续检测低电平持续时间是否符合时序,排除掉误触发。这样就完成了器件的复位操作。
我们把GPIO初始化和复位封装一下,加入到main函数中后,就完成了初始化了,代码如下:

void DS18B20_Open(void)
{
    DS18B20_GPIO_Config ();		
    DS18B20_Rst();		
}

DS18B20的初始化我们就说到这里,下一章我们介绍温度读取的剩下部分。

原创文章,作者:小峰,如若转载,请注明出处:http://www.wfblog.com/archives/443.html

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息