STM32-HAL库 驱动DS18B20温度传感器 -- 2024.10.8

打印 上一主题 下一主题

主题 664|帖子 664|积分 1992

目录
一、教程简介
二、驱动理论讲解
三、CubeMX生成底层代码
四、Keil5编写代码
五、实验效果

一、教程简介

        本教程面向初学者,只介绍DS18B20的常用功能,但也能满意大部分的运用需求。跟着本教程操作,可在10分钟内解决DS18b20通信难题。
二、驱动理论讲解

        DS18b20支持多传感器共用一个引脚,但本教程只教利用一个温湿度传感器。利用DS18b20可分为下面两个步骤进行
(一)初始化:
        1、将引脚初始化为推挽输出、上拉。
        2、发送复位脉冲:引脚输出大于480us的低电平复位信号(发起600us),延时600us之后,需将引脚拉高并延时15us。
        3、检测存在脉冲:将引脚设置为上拉输入,并检测低电平到来的时间,若高出100us还没检测到低电平,则初始化失败。检测到低电平后开始盘算时间,若低高出240us还没检测到高电平,则初始化失败。
(二)获取温度:
        1、配置单DS18b20模式:重复初始化操作后发送下令:0xCC
        2、发送温度转换下令:发送0x44
        3、配置单DS18b20模式:重复初始化操作后发送下令:0xCC
        4、发送读取下令:发送0xBE
        5、吸收两个字节的温度数据
三、CubeMX生成底层代码

1、芯片选择:这里选用STM32F103C8t6

 2、配置Debug模式

3、 配置外部高速时钟

4、 配置时钟速率

5、 配置DS18b20引脚

6、配置串口

7、输出工程文件



四、Keil5编写代码

1、ds18b20.c 代码
  1. /* 包含头文件 ----------------------------------------------------------------*/
  2. #include "ds18b20.h"
  3. /**
  4.   * 函数功能: DS18B20 初始化函数
  5.   * 返 回 值: 1为初始化失败,0为初始化成功
  6.   */
  7. uint8_t DS18B20_Init(void)
  8. {
  9.   DS18B20_Mode_Out_PP();            //推挽输出模式
  10.         
  11.   DS18B20_Dout_HIGH();                                                  //输出高电平
  12.         
  13.   DS18B20_Rst();                                                        //输出复位脉冲
  14.   
  15.   return DS18B20_Presence ();                          //返回响应情况
  16. }
  17. /**
  18.   * 函数功能: 使DS18B20-DATA引脚变为上拉输入模式
  19.   */
  20. static void DS18B20_Mode_IPU(void)
  21. {
  22.   GPIO_InitTypeDef GPIO_InitStruct;
  23.   
  24.   /* 串口外设功能GPIO配置 */
  25.   GPIO_InitStruct.Pin   = DS18b20_Pin;
  26.   GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  27.   GPIO_InitStruct.Pull  = GPIO_PULLUP;
  28.   HAL_GPIO_Init(DS18b20_GPIO_Port, &GPIO_InitStruct);
  29.         
  30. }
  31. /**
  32.   * 函数功能: 使DS18B20-DATA引脚变为推挽输出模式
  33.   */
  34. static void DS18B20_Mode_Out_PP(void)
  35. {
  36.   GPIO_InitTypeDef GPIO_InitStruct;
  37.   
  38.   /* 串口外设功能GPIO配置 */
  39.   GPIO_InitStruct.Pin = DS18b20_Pin;
  40.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  41.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  42.   HAL_GPIO_Init(DS18b20_GPIO_Port, &GPIO_InitStruct);         
  43. }
  44. /**
  45.   * 函数功能: 主机给从机发送复位脉冲
  46.   */
  47. static void DS18B20_Rst(void)
  48. {
  49.    DS18B20_Mode_Out_PP(); /* 主机设置为推挽输出 */
  50.    DS18B20_Dout_LOW();    /* 主机输出低电平 */
  51.    DS18B20_Delay(750);    /* 主机至少产生480us的低电平复位信号 */
  52.    DS18B20_Dout_HIGH();   /* 主机在产生复位信号后,需将总线拉高 */
  53.    DS18B20_Delay(15);     /* 从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲 */
  54. }
  55. /**
  56.   * 函数功能: 检测从机给主机返回的存在脉冲
  57.   * 返 回 值: 0:成功,1:失败
  58.   */
  59. static uint8_t DS18B20_Presence(void)
  60. {
  61.    uint8_t pulse_time = 0;
  62.    /* 主机设置为上拉输入 */
  63.    DS18B20_Mode_IPU();
  64.    
  65.    /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号
  66.     * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
  67.     */
  68.    while( DS18B20_Data_IN() && pulse_time<100 )
  69.    {
  70.       pulse_time++;
  71.       DS18B20_Delay(1);
  72.    }        
  73.    /* 经过100us后,存在脉冲都还没有到来*/
  74.    if( pulse_time >=100 )
  75.       return 1;
  76.    else
  77.       pulse_time = 0;
  78.    
  79.    /* 存在脉冲到来,且存在的时间不能超过240us */
  80.    while( !DS18B20_Data_IN() && pulse_time<240 )
  81.    {
  82.        pulse_time++;
  83.        DS18B20_Delay(1);
  84.    }        
  85.    if( pulse_time >=240 )
  86.        return 1;
  87.    else
  88.        return 0;
  89. }
  90. /**
  91.   * 函数功能: 从DS18B20读取一个bit
  92.   * 返 回 值: 读取到的数据
  93.   */
  94. static uint8_t DS18B20_ReadBit(void)
  95. {
  96.    uint8_t dat;
  97.    
  98.    /* 读0和读1的时间至少要大于60us */        
  99.    DS18B20_Mode_Out_PP();
  100.    /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
  101.    DS18B20_Dout_LOW();
  102.    DS18B20_Delay(10);
  103.    
  104.    /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
  105.    DS18B20_Mode_IPU();
  106.    //Delay_us(2);
  107.    
  108.    if( DS18B20_Data_IN() == SET )
  109.            dat = 1;
  110.    else
  111.            dat = 0;
  112.    
  113.    /* 这个延时参数请参考时序图 */
  114.    DS18B20_Delay(45);
  115.    
  116.    return dat;
  117. }
  118. /**
  119.   * 函数功能: 从DS18B20读一个字节,低位先行
  120.   * 返 回 值: 读到的数据
  121.   */
  122. static uint8_t DS18B20_ReadByte(void)
  123. {
  124.    uint8_t i, j, dat = 0;        
  125.    for(i=0; i<8; i++)
  126.    {
  127.       j = DS18B20_ReadBit();               
  128.       dat = (dat) | (j<<i);
  129.    }
  130.    return dat;
  131. }
  132. /**
  133.   * 函数功能: 写一个字节到DS18B20,低位先行
  134.   * 输入参数: dat:待写入数据
  135.   */
  136. static void DS18B20_WriteByte(uint8_t dat)
  137. {
  138.    uint8_t i, testb;
  139.    DS18B20_Mode_Out_PP();
  140.    for( i=0; i<8; i++ )
  141.    {
  142.       testb = dat&0x01;
  143.       dat = dat>>1;               
  144.       /* 写0和写1的时间至少要大于60us */
  145.       if (testb)
  146.       {                        
  147.          DS18B20_Dout_LOW();
  148.          /* 1us < 这个延时 < 15us */
  149.          DS18B20_Delay(8);
  150.          
  151.          DS18B20_Dout_HIGH();
  152.          DS18B20_Delay(58);
  153.       }           
  154.       else
  155.       {                  
  156.          DS18B20_Dout_LOW();
  157.          /* 60us < Tx 0 < 120us */
  158.          DS18B20_Delay(70);
  159.          
  160.          DS18B20_Dout_HIGH();               
  161.          /* 1us < Trec(恢复时间) < 无穷大*/
  162.          DS18B20_Delay(2);
  163.       }
  164.    }
  165. }
  166. /**
  167.   * 函数功能: 跳过匹配 DS18B20 ROM
  168.   */
  169. static void DS18B20_SkipRom ( void )
  170. {
  171.    DS18B20_Rst();                  
  172.    DS18B20_Presence();                 
  173.    DS18B20_WriteByte(0XCC);                /* 跳过 ROM */        
  174. }
  175. /**
  176.   * 函数功能: 获取 DS18B20 温度值
  177.   * 返 回 值: 浮点型温度值
  178.   */
  179. float DS18B20_GetTemp_SkipRom ( void )
  180. {
  181.    uint8_t tpmsb, tplsb;
  182.    short s_tem;
  183.    float f_tem;
  184.    
  185.    DS18B20_SkipRom ();
  186.    DS18B20_WriteByte(0X44);                                /* 开始转换 */
  187.    
  188.    DS18B20_SkipRom ();
  189.          DS18B20_WriteByte(0XBE);                                /* 读温度值 */
  190.    
  191.    tplsb = DS18B20_ReadByte();                 
  192.    tpmsb = DS18B20_ReadByte();
  193.    
  194.    s_tem = tpmsb<<8;
  195.    s_tem = s_tem | tplsb;
  196.    
  197.    if( s_tem < 0 )                /* 负温度 */
  198.      f_tem = (~s_tem+1) * 0.0625;        
  199.    else
  200.      f_tem = s_tem * 0.0625;
  201.    
  202.    return f_tem;         
  203. }
  204. /**
  205.   * 微妙延时函数
  206.   * 全系列通用,只需要将宏定义CPU_FREQUENCY_MHZ根据时钟主频修改即可。
  207.   * 系统滴答定时器是HAL库初始化的,且必须有HAL库初始化。
  208.   */
  209. #define CPU_FREQUENCY_MHZ   (int)(HAL_RCC_GetHCLKFreq()/1000000)                // 自动获取STM32时钟主频
  210. void DS18B20_Delay(__IO uint32_t delay)  
  211. {
  212.    int last, curr, val;
  213.    int temp;
  214.    while (delay != 0)
  215.    {
  216.       temp = delay > 900 ? 900 : delay;
  217.       last = SysTick->VAL;
  218.       curr = last - CPU_FREQUENCY_MHZ * temp;
  219.       if (curr >= 0)
  220.       {
  221.          do
  222.          {
  223.              val = SysTick->VAL;
  224.          }
  225.          while ((val < last) && (val >= curr));
  226.       }
  227.       else
  228.       {
  229.          curr += CPU_FREQUENCY_MHZ * 1000;
  230.          do
  231.          {
  232.              val = SysTick->VAL;
  233.          }
  234.          while ((val <= last) || (val > curr));
  235.       }
  236.       delay -= temp;
  237.     }
  238. }
复制代码
2、ds18b20.h 代码
  1. #ifndef __DS18B20_H
  2. #define __DS18B20_H
  3. /* 包含头文件 ----------------------------------------------------------------*/
  4. #include "main.h"
  5. /* 引脚操作函数宏定义 --------------------------------------------------------*/
  6. #define DS18B20_Dout_LOW()               HAL_GPIO_WritePin(DS18b20_GPIO_Port,DS18b20_Pin,GPIO_PIN_RESET)
  7. #define DS18B20_Dout_HIGH()              HAL_GPIO_WritePin(DS18b20_GPIO_Port,DS18b20_Pin,GPIO_PIN_SET)
  8. #define DS18B20_Data_IN()                HAL_GPIO_ReadPin(DS18b20_GPIO_Port,DS18b20_Pin)
  9. /* 函数声明 ------------------------------------------------------------------*/
  10. void                 DS18B20_Rst(void);
  11. void                 DS18B20_SkipRom(void);
  12. void                 DS18B20_Mode_IPU(void);
  13. void                 DS18B20_Mode_Out_PP(void);
  14. void                 DS18B20_WriteByte(uint8_t dat);
  15. void                 DS18B20_Delay(__IO uint32_t delay);
  16. float   DS18B20_GetTemp_SkipRom(void);
  17. uint8_t DS18B20_Init(void);
  18. uint8_t DS18B20_ReadBit(void);
  19. uint8_t DS18B20_Presence(void);
  20. uint8_t DS18B20_ReadByte(void);
  21. #endif
复制代码
3、main.c 参考调用代码
  1. /* USER CODE END Header */
  2. /* Includes ------------------------------------------------------------------*/
  3. #include "main.h"
  4. #include "usart.h"
  5. #include "gpio.h"
  6. /* Private includes ----------------------------------------------------------*/
  7. /* USER CODE BEGIN Includes */
  8. #include "ds18b20.h"
  9. #include "stdio.h"
  10. /* USER CODE END Includes */
  11. /* Private typedef -----------------------------------------------------------*/
  12. /* USER CODE BEGIN PTD */
  13. /* USER CODE END PTD */
  14. /* Private define ------------------------------------------------------------*/
  15. /* USER CODE BEGIN PD */
  16. char  Tx_Buf[30] = {0};
  17. float Temp = 0;
  18. /* USER CODE END PD */
  19. /* Private macro -------------------------------------------------------------*/
  20. /* USER CODE BEGIN PM */
  21. /* USER CODE END PM */
  22. /* Private variables ---------------------------------------------------------*/
  23. /* USER CODE BEGIN PV */
  24. /* USER CODE END PV */
  25. /* Private function prototypes -----------------------------------------------*/
  26. void SystemClock_Config(void);
  27. /* USER CODE BEGIN PFP */
  28. /* USER CODE END PFP */
  29. /* Private user code ---------------------------------------------------------*/
  30. /* USER CODE BEGIN 0 */
  31. /* USER CODE END 0 */
  32. /**
  33.   * @brief  The application entry point.
  34.   * @retval int
  35.   */
  36. int main(void)
  37. {
  38.   /* USER CODE BEGIN 1 */
  39.   /* USER CODE END 1 */
  40.   /* MCU Configuration--------------------------------------------------------*/
  41.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  42.   HAL_Init();
  43.   /* USER CODE BEGIN Init */
  44.   /* USER CODE END Init */
  45.   /* Configure the system clock */
  46.   SystemClock_Config();
  47.   /* USER CODE BEGIN SysInit */
  48.   /* USER CODE END SysInit */
  49.   /* Initialize all configured peripherals */
  50.   MX_GPIO_Init();
  51.   MX_USART1_UART_Init();
  52.   /* USER CODE BEGIN 2 */
  53.         while(DS18B20_Init())
  54.         {
  55.                 HAL_UART_Transmit(&huart1,(uint8_t*)"DS18b20初始化失败\r\n",19,100);
  56.                 HAL_Delay(1000);
  57.         }
  58.         HAL_UART_Transmit(&huart1,(uint8_t*)"DS18b20初始化成功\r\n",19,100);
  59.   /* USER CODE END 2 */
  60.   /* Infinite loop */
  61.   /* USER CODE BEGIN WHILE */
  62.   while (1)
  63.   {
  64.                 Temp = DS18B20_GetTemp_SkipRom();
  65.                 sprintf(Tx_Buf,"温度:%0.3f \r\n",Temp);
  66.                 HAL_UART_Transmit(&huart1,(uint8_t*)Tx_Buf,15,100);
  67.                 HAL_Delay(1000);
  68.     /* USER CODE END WHILE */
  69.     /* USER CODE BEGIN 3 */
  70.   }
  71.   /* USER CODE END 3 */
  72. }
复制代码
五、实验效果

        通过本驱动利用DS18b20丈量出来的环境温度,与米家温湿度计丈量的效果仅仅相差0.012摄氏度,丈量精度非常可观。

 六、特别说明



  • 同学们在操作的过程中遇到的问题可在评论区留言,我看到后会第一时间回复。
  • 想看其他传感器的教程也可在评论区留言,我会按照大家的需求来修改教程内容。
  • 若您以为本教程对您有所帮助,请点赞、收藏,这是我持续更新的最大动力,感谢您!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

干翻全岛蛙蛙

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表