[STM32F4] STM32F4 HAL库开发 -- 温度传感器(DS18B20)

[复制链接]
 楼主| 雨果喝水 发表于 2023-8-27 17:38 | 显示全部楼层 |阅读模式
简介1、概述

DS18B20 是 DALLAS 最新单线数字温度传感器,新的"一线器件"体积更小、适用电压更宽、更经济。Dallas 半导体公司的数字化温度传感器 DS1820 是世界上第一片支持 "一线总线"接口的温度传感器。

DS18B20采用的单总线协议,也就是只需占用主机一个I/O口,无需其他外围电路,直接将环境温度转换为数字信号,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。另外,以"一线总线"的数字方式传输,大大提高了系统的抗干扰性。适合于恶劣环境的现场温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。

2、特性

(1) 具有独特的单总线接口,与主机主需要一个线即可实现双向通信;
(2) 测温范围为-55+125℃,在-10+85℃时,精度为±0.5℃;
(3) 可编程的分辨率为 9~12 位,对应的可分辨温度分别为 0.5℃、0.25℃、0.125℃和 0.0625℃;
(4) 在9 位分辨率时,最多在93.75ms 内把温度值转换为数字,在12 位分辨率时,最多在 750ms 内把温度值转换为数字;
(5) 负压特性,电源极性接反时,温度计不会因发热而烧毁,但不能正常工作。
(6) 工作电压范围宽,电压范围为3.0~5.5V,还可用数据线供电;
(7) 支持多点组网,多个DS18B20可以并联实现多点组网测温。值得注意的是,如果数量过多,需要解决供电问题,否则电压过低会导致信号传输不稳定;
(8) 测量结果采用数字信号输出,同时具有CRC校验,具较强的抗干扰和纠错能力。


 楼主| 雨果喝水 发表于 2023-8-27 17:38 | 显示全部楼层
外形结构
DS18B20 内部结构主要由四部分组成:64 位光刻 ROM、温度传感器、非挥发的温度报警触发器 TH 和 TL、配置寄存器。DS18B20 的管脚排列如下图所示。
 楼主| 雨果喝水 发表于 2023-8-27 17:38 | 显示全部楼层
 楼主| 雨果喝水 发表于 2023-8-27 17:38 | 显示全部楼层
其中与操作有关的有:64位光刻ROM、9个字节的RAM存储器、温度传感器、EERPOM(温度报警寄存器TH和TL、配置寄存器)
 楼主| 雨果喝水 发表于 2023-8-27 17:39 | 显示全部楼层
二、HAL库完整代码
 楼主| 雨果喝水 发表于 2023-8-27 17:39 | 显示全部楼层
  1. /* Includes*********************************************************************/
  2. #include "stm32f103_DS18B20.h"

  3. /* Private typedef -----------------------------------------------------------*/
  4. /* Private define ------------------------------------------------------------*/
  5. /* Private macro -------------------------------------------------------------*/
  6. /* Private variables ---------------------------------------------------------*/
  7. /* Private function prototypes -----------------------------------------------*/
  8. /* Private functions ---------------------------------------------------------*/
  9. static void DS18B20_Mode_IPU(void);
  10. static void DS18B20_Mode_Out_PP(void);
  11. static void DS18B20_Rst(void);
  12. static uint8_t DS18B20_Presence(void);
  13. static uint8_t DS18B20_ReadBit(void);
  14. static uint8_t DS18B20_ReadByte(void);
  15. static void DS18B20_WriteByte(uint8_t dat);
  16. static void DS18B20_SkipRom(void);
  17. static void DS18B20_MatchRom(void);

  18. #define CPU_FREQUENCY_MHZ    72                // STM32时钟主频
  19. void delay_us(__IO uint32_t delay)
  20. {
  21.     int last, curr, val;
  22.     int temp;

  23.     while (delay != 0)
  24.     {
  25.         temp = delay > 900 ? 900 : delay;
  26.         last = SysTick->VAL;
  27.         curr = last - CPU_FREQUENCY_MHZ * temp;
  28.         if (curr >= 0)
  29.         {
  30.             do
  31.             {
  32.                 val = SysTick->VAL;
  33.             }
  34.             while ((val < last) && (val >= curr));
  35.         }
  36.         else
  37.         {
  38.             curr += CPU_FREQUENCY_MHZ * 1000;
  39.             do
  40.             {
  41.                 val = SysTick->VAL;
  42.             }
  43.             while ((val <= last) || (val > curr));
  44.         }
  45.         delay -= temp;
  46.     }
  47. }

  48. static void delay_us_bak(uint16_t time)
  49. {
  50.         uint8_t i;

  51.   while(time)
  52.   {   
  53.           for (i = 0; i < 10; i++)
  54.     {
  55.       
  56.     }
  57.     time--;
  58.   }
  59. }

  60. /**
  61.   * [url=home.php?mod=space&uid=247401]@brief[/url]  DS18B20 初始化函数
  62.   * @param  None
  63.   * @retval None
  64.   */
  65. uint8_t DS18B20_Init(void)
  66. {
  67.   DS18B20_Dout_GPIO_CLK_ENABLE();
  68.   
  69.   DS18B20_Mode_Out_PP();
  70.        
  71.         DS18B20_Dout_HIGH();
  72.        
  73.         DS18B20_Rst();
  74.   
  75.   return DS18B20_Presence ();
  76. }

  77. /**
  78.   * @brief  使DS18B20-DATA引脚变为上拉输入模式
  79.   * @param  None
  80.   * @retval None
  81.   */
  82. static void DS18B20_Mode_IPU(void)
  83. {
  84.   GPIO_InitTypeDef GPIO_InitStruct;
  85.   
  86.   /* 串口外设功能GPIO配置 */
  87.   GPIO_InitStruct.Pin   = DS18B20_Dout_PIN;
  88.   GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  89.   GPIO_InitStruct.Pull  = GPIO_PULLUP;
  90.   HAL_GPIO_Init(DS18B20_Dout_PORT, &GPIO_InitStruct);
  91. }

  92. /**
  93.   * @brief  使DS18B20-DATA引脚变为推挽输出模式
  94.   * @param  None
  95.   * @retval None
  96.   */
  97. static void DS18B20_Mode_Out_PP(void)
  98. {
  99.   GPIO_InitTypeDef GPIO_InitStruct;
  100.   
  101.   /* 串口外设功能GPIO配置 */
  102.   GPIO_InitStruct.Pin = DS18B20_Dout_PIN;
  103.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  104.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  105.   HAL_GPIO_Init(DS18B20_Dout_PORT, &GPIO_InitStruct);          
  106. }

  107. /**
  108.   * @brief  主机给从机发送复位脉冲
  109.   * @param  None
  110.   * @retval None
  111.   */
  112. static void DS18B20_Rst(void)
  113. {
  114.         /* 主机设置为推挽输出 */
  115.         DS18B20_Mode_Out_PP();
  116.        
  117.         DS18B20_Dout_LOW();
  118.   
  119.         /* 主机至少产生480us的低电平复位信号 */
  120.         delay_us(750);
  121.        
  122.         /* 主机在产生复位信号后,需将总线拉高 */
  123.         DS18B20_Dout_HIGH();
  124.        
  125.         /*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
  126.         delay_us(15);
  127. }

  128. /**
  129.   * @brief  检测从机给主机返回的存在脉冲
  130.   * @param  None
  131.   * @retval 0:成功,1:失败
  132.   */
  133. static uint8_t DS18B20_Presence(void)
  134. {
  135.         uint8_t pulse_time = 0;
  136.        
  137.         /* 主机设置为上拉输入 */
  138.         DS18B20_Mode_IPU();
  139.        
  140.         /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号
  141.          * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
  142.          */
  143.         while( DS18B20_Data_IN() && pulse_time<100 )
  144.         {
  145.                 pulse_time++;
  146.                 delay_us(1);
  147.         }       
  148.         /* 经过100us后,存在脉冲都还没有到来*/
  149.         if( pulse_time >=100 )
  150.                 return 1;
  151.         else
  152.                 pulse_time = 0;
  153.        
  154.         /* 存在脉冲到来,且存在的时间不能超过240us */
  155.         while( !DS18B20_Data_IN() && pulse_time<240 )
  156.         {
  157.                 pulse_time++;
  158.                 delay_us(1);
  159.         }       
  160.         if( pulse_time >=240 )
  161.                 return 1;
  162.         else
  163.                 return 0;
  164. }

  165. /**
  166.   * @brief  从DS18B20读取一个bit
  167.   * @param  None
  168.   * @retval 读取到的数据
  169.   */
  170. static uint8_t DS18B20_ReadBit(void)
  171. {
  172.         uint8_t dat;
  173.        
  174.         /* 读0和读1的时间至少要大于60us */       
  175.         DS18B20_Mode_Out_PP();
  176.         /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
  177.         DS18B20_Dout_LOW();
  178.         delay_us(10);
  179.        
  180.         /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
  181.         DS18B20_Mode_IPU();
  182.         //Delay_us(2);
  183.        
  184.         if( DS18B20_Data_IN() == SET )
  185.                 dat = 1;
  186.         else
  187.                 dat = 0;
  188.        
  189.         /* 这个延时参数请参考时序图 */
  190.         delay_us(45);
  191.        
  192.         return dat;
  193. }

  194. /**
  195.   * @brief  从DS18B20读一个字节,低位先行
  196.   * @param  None
  197.   * @retval 读取到的数据
  198.   */
  199. static uint8_t DS18B20_ReadByte(void)
  200. {
  201.         uint8_t i, j, dat = 0;       
  202.        
  203.         for(i=0; i<8; i++)
  204.         {
  205.                 j = DS18B20_ReadBit();               
  206.                 dat = (dat) | (j<<i);
  207.         }
  208.        
  209.         return dat;
  210. }

  211. /**
  212.   * @brief  写一个字节到DS18B20,低位先行
  213.   * @param  dat:待写入数据
  214.   * @retval None
  215.   */
  216. static void DS18B20_WriteByte(uint8_t dat)
  217. {
  218.         uint8_t i, testb;
  219.         DS18B20_Mode_Out_PP();
  220.        
  221.         for( i=0; i<8; i++ )
  222.         {
  223.                 testb = dat&0x01;
  224.                 dat = dat>>1;               
  225.                 /* 写0和写1的时间至少要大于60us */
  226.                 if (testb)
  227.                 {                       
  228.                         DS18B20_Dout_LOW();
  229.                         /* 1us < 这个延时 < 15us */
  230.                         delay_us(8);
  231.                        
  232.                         DS18B20_Dout_HIGH();
  233.                         delay_us(58);
  234.                 }               
  235.                 else
  236.                 {                       
  237.                         DS18B20_Dout_LOW();
  238.                         /* 60us < Tx 0 < 120us */
  239.                         delay_us(70);
  240.                        
  241.                         DS18B20_Dout_HIGH();               
  242.                         /* 1us < Trec(恢复时间) < 无穷大*/
  243.                         delay_us(2);
  244.                 }
  245.         }
  246. }

  247. /**
  248.   * @brief  跳过匹配 DS18B20 ROM
  249.   * @param  None
  250.   * @retval None
  251.   */
  252. static void DS18B20_SkipRom ( void )
  253. {
  254.         DS18B20_Rst();                  
  255.         DS18B20_Presence();                
  256.         DS18B20_WriteByte(0XCC);                /* 跳过 ROM */       
  257. }


  258. /**
  259.   * @brief  执行匹配 DS18B20 ROM
  260.   * @param  None
  261.   * @retval None
  262.   */
  263. static void DS18B20_MatchRom ( void )
  264. {
  265.         DS18B20_Rst();                  
  266.         DS18B20_Presence();                
  267.         DS18B20_WriteByte(0X55);                /* 匹配 ROM */       
  268. }

  269. /*
  270. * 存储的温度是16 位的带符号扩展的二进制补码形式
  271. * 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位
  272. *
  273. *         |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|
  274. * 低字节  | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |
  275. *
  276. *
  277. *         |-----符号位:0->正  1->负-------|-----------整数-----------|
  278. * 高字节  |  s  |  s  |  s  |  s  |    s   |   2^6  |   2^5  |   2^4  |
  279. *
  280. *
  281. * 温度 = 符号位 + 整数 + 小数*0.0625
  282. */
  283. /**
  284.   * @brief  在跳过匹配 ROM 情况下获取 DS18B20 温度值
  285.   * @param  None
  286.   * @retval 温度值
  287.   */
  288. float DS18B20_GetTemp_SkipRom ( void )
  289. {
  290.         uint8_t tpmsb, tplsb;
  291.         short s_tem;
  292.         float f_tem;
  293.        
  294.         DS18B20_SkipRom ();
  295.         DS18B20_WriteByte(0X44);                                /* 开始转换 */
  296.        
  297.         DS18B20_SkipRom ();
  298.   DS18B20_WriteByte(0XBE);                                /* 读温度值 */
  299.        
  300.         tplsb = DS18B20_ReadByte();                 
  301.         tpmsb = DS18B20_ReadByte();
  302.        
  303.        
  304.         s_tem = tpmsb<<8;
  305.         s_tem = s_tem | tplsb;
  306.        
  307.         if( s_tem < 0 )                /* 负温度 */
  308.                 f_tem = (~s_tem+1) * 0.0625;       
  309.         else
  310.                 f_tem = s_tem * 0.0625;
  311.        
  312.         return f_tem;        
  313. }


  314. /**
  315.   * @brief  在匹配 ROM 情况下获取 DS18B20 温度值
  316.   * @param  ds18b20_id:用于存放 DS18B20 序列号的数组的首地址
  317.   * @retval None
  318.   */
  319. void DS18B20_ReadId ( uint8_t * ds18b20_id )
  320. {
  321.         uint8_t uc;
  322.                
  323.         DS18B20_WriteByte(0x33);       //读取序列号
  324.        
  325.         for ( uc = 0; uc < 8; uc ++ )
  326.           ds18b20_id [ uc ] = DS18B20_ReadByte();       
  327. }

  328. /**
  329.   * @brief  在匹配 ROM 情况下获取 DS18B20 温度值
  330.   * @param  ds18b20_id:存放 DS18B20 序列号的数组的首地址
  331.   * @retval 温度值
  332.   */
  333. float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id )
  334. {
  335.         uint8_t tpmsb, tplsb, i;
  336.         short s_tem;
  337.         float f_tem;
  338.        
  339.        
  340.         DS18B20_MatchRom ();            //匹配ROM
  341.        
  342.   for(i=0;i<8;i++)
  343.                 DS18B20_WriteByte ( ds18b20_id [ i ] );       
  344.        
  345.         DS18B20_WriteByte(0X44);                                /* 开始转换 */

  346.        
  347.         DS18B20_MatchRom ();            //匹配ROM
  348.        
  349.         for(i=0;i<8;i++)
  350.                 DS18B20_WriteByte ( ds18b20_id [ i ] );       
  351.        
  352.         DS18B20_WriteByte(0XBE);                                /* 读温度值 */
  353.        
  354.         tplsb = DS18B20_ReadByte();                 
  355.         tpmsb = DS18B20_ReadByte();
  356.        
  357.        
  358.         s_tem = tpmsb<<8;
  359.         s_tem = s_tem | tplsb;
  360.        
  361.         if( s_tem < 0 )                /* 负温度 */
  362.                 f_tem = (~s_tem+1) * 0.0625;       
  363.         else
  364.                 f_tem = s_tem * 0.0625;
  365.        
  366.         return f_tem;                
  367. }
Wordsworth 发表于 2024-9-16 07:21 | 显示全部楼层

改变测试负载的值,再次测试输出的电流和电压
Clyde011 发表于 2024-9-16 08:24 | 显示全部楼层

表征负载能力的指标是负载能力和负载能力上升时间
公羊子丹 发表于 2024-9-16 09:17 | 显示全部楼层

环氧树脂由于硬度的原因不能用于应力敏感和含有贴片元件的模块灌封,在模块电源中基本被淘汰
万图 发表于 2024-9-16 10:20 | 显示全部楼层

直至电感器饱和,使开关器件烧毁。好的元器件就到唯样商城。图中的D3与N3构成的磁通复位电路,提供了泄放多余磁能的渠道
Uriah 发表于 2024-9-16 11:23 | 显示全部楼层

一些静态测试参数还包括波浪、纹波、起伏和静态输出电压精度。
帛灿灿 发表于 2024-9-16 13:19 | 显示全部楼层

测试参数包括电源的输出电压、输出电流、负载能力、压降、效率和输出波形
Bblythe 发表于 2024-9-16 14:22 | 显示全部楼层

逐渐变细的孔(也称为邮票孔)变得越来越普遍
周半梅 发表于 2024-9-16 16:18 | 显示全部楼层

正激:脉冲变压器的原/副边相位关系
Pulitzer 发表于 2024-9-16 17:21 | 显示全部楼层

是两根线分别对地的噪声
童雨竹 发表于 2024-9-16 19:17 | 显示全部楼层

大于1的定义为极高导热的性能,而对于模块电源此水平的导热系数是无法达到其散热功能的需求
您需要登录后才可以回帖 登录 | 注册

本版积分规则

90

主题

1213

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部

90

主题

1213

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部