打印
[STM32F4]

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

[复制链接]
1268|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
简介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、配置寄存器)

使用特权

评论回复
5
雨果喝水|  楼主 | 2023-8-27 17:39 | 只看该作者
二、HAL库完整代码

使用特权

评论回复
6
雨果喝水|  楼主 | 2023-8-27 17:39 | 只看该作者
/* Includes*********************************************************************/
#include "stm32f103_DS18B20.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static void DS18B20_Mode_IPU(void);
static void DS18B20_Mode_Out_PP(void);
static void DS18B20_Rst(void);
static uint8_t DS18B20_Presence(void);
static uint8_t DS18B20_ReadBit(void);
static uint8_t DS18B20_ReadByte(void);
static void DS18B20_WriteByte(uint8_t dat);
static void DS18B20_SkipRom(void);
static void DS18B20_MatchRom(void);

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

    while (delay != 0)
    {
        temp = delay > 900 ? 900 : delay;
        last = SysTick->VAL;
        curr = last - CPU_FREQUENCY_MHZ * temp;
        if (curr >= 0)
        {
            do
            {
                val = SysTick->VAL;
            }
            while ((val < last) && (val >= curr));
        }
        else
        {
            curr += CPU_FREQUENCY_MHZ * 1000;
            do
            {
                val = SysTick->VAL;
            }
            while ((val <= last) || (val > curr));
        }
        delay -= temp;
    }
}

static void delay_us_bak(uint16_t time)
{
        uint8_t i;

  while(time)
  {   
          for (i = 0; i < 10; i++)
    {
      
    }
    time--;
  }
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  DS18B20 初始化函数
  * @param  None
  * @retval None
  */
uint8_t DS18B20_Init(void)
{
  DS18B20_Dout_GPIO_CLK_ENABLE();
  
  DS18B20_Mode_Out_PP();
       
        DS18B20_Dout_HIGH();
       
        DS18B20_Rst();
  
  return DS18B20_Presence ();
}

/**
  * @brief  使DS18B20-DATA引脚变为上拉输入模式
  * @param  None
  * @retval None
  */
static void DS18B20_Mode_IPU(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* 串口外设功能GPIO配置 */
  GPIO_InitStruct.Pin   = DS18B20_Dout_PIN;
  GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull  = GPIO_PULLUP;
  HAL_GPIO_Init(DS18B20_Dout_PORT, &GPIO_InitStruct);
}

/**
  * @brief  使DS18B20-DATA引脚变为推挽输出模式
  * @param  None
  * @retval None
  */
static void DS18B20_Mode_Out_PP(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  
  /* 串口外设功能GPIO配置 */
  GPIO_InitStruct.Pin = DS18B20_Dout_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(DS18B20_Dout_PORT, &GPIO_InitStruct);          
}

/**
  * @brief  主机给从机发送复位脉冲
  * @param  None
  * @retval None
  */
static void DS18B20_Rst(void)
{
        /* 主机设置为推挽输出 */
        DS18B20_Mode_Out_PP();
       
        DS18B20_Dout_LOW();
  
        /* 主机至少产生480us的低电平复位信号 */
        delay_us(750);
       
        /* 主机在产生复位信号后,需将总线拉高 */
        DS18B20_Dout_HIGH();
       
        /*从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲*/
        delay_us(15);
}

/**
  * @brief  检测从机给主机返回的存在脉冲
  * @param  None
  * @retval 0:成功,1:失败
  */
static uint8_t DS18B20_Presence(void)
{
        uint8_t pulse_time = 0;
       
        /* 主机设置为上拉输入 */
        DS18B20_Mode_IPU();
       
        /* 等待存在脉冲的到来,存在脉冲为一个60~240us的低电平信号
         * 如果存在脉冲没有来则做超时处理,从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
         */
        while( DS18B20_Data_IN() && pulse_time<100 )
        {
                pulse_time++;
                delay_us(1);
        }       
        /* 经过100us后,存在脉冲都还没有到来*/
        if( pulse_time >=100 )
                return 1;
        else
                pulse_time = 0;
       
        /* 存在脉冲到来,且存在的时间不能超过240us */
        while( !DS18B20_Data_IN() && pulse_time<240 )
        {
                pulse_time++;
                delay_us(1);
        }       
        if( pulse_time >=240 )
                return 1;
        else
                return 0;
}

/**
  * @brief  从DS18B20读取一个bit
  * @param  None
  * @retval 读取到的数据
  */
static uint8_t DS18B20_ReadBit(void)
{
        uint8_t dat;
       
        /* 读0和读1的时间至少要大于60us */       
        DS18B20_Mode_Out_PP();
        /* 读时间的起始:必须由主机产生 >1us <15us 的低电平信号 */
        DS18B20_Dout_LOW();
        delay_us(10);
       
        /* 设置成输入,释放总线,由外部上拉电阻将总线拉高 */
        DS18B20_Mode_IPU();
        //Delay_us(2);
       
        if( DS18B20_Data_IN() == SET )
                dat = 1;
        else
                dat = 0;
       
        /* 这个延时参数请参考时序图 */
        delay_us(45);
       
        return dat;
}

/**
  * @brief  从DS18B20读一个字节,低位先行
  * @param  None
  * @retval 读取到的数据
  */
static uint8_t DS18B20_ReadByte(void)
{
        uint8_t i, j, dat = 0;       
       
        for(i=0; i<8; i++)
        {
                j = DS18B20_ReadBit();               
                dat = (dat) | (j<<i);
        }
       
        return dat;
}

/**
  * @brief  写一个字节到DS18B20,低位先行
  * @param  dat:待写入数据
  * @retval None
  */
static void DS18B20_WriteByte(uint8_t dat)
{
        uint8_t i, testb;
        DS18B20_Mode_Out_PP();
       
        for( i=0; i<8; i++ )
        {
                testb = dat&0x01;
                dat = dat>>1;               
                /* 写0和写1的时间至少要大于60us */
                if (testb)
                {                       
                        DS18B20_Dout_LOW();
                        /* 1us < 这个延时 < 15us */
                        delay_us(8);
                       
                        DS18B20_Dout_HIGH();
                        delay_us(58);
                }               
                else
                {                       
                        DS18B20_Dout_LOW();
                        /* 60us < Tx 0 < 120us */
                        delay_us(70);
                       
                        DS18B20_Dout_HIGH();               
                        /* 1us < Trec(恢复时间) < 无穷大*/
                        delay_us(2);
                }
        }
}

/**
  * @brief  跳过匹配 DS18B20 ROM
  * @param  None
  * @retval None
  */
static void DS18B20_SkipRom ( void )
{
        DS18B20_Rst();                  
        DS18B20_Presence();                
        DS18B20_WriteByte(0XCC);                /* 跳过 ROM */       
}


/**
  * @brief  执行匹配 DS18B20 ROM
  * @param  None
  * @retval None
  */
static void DS18B20_MatchRom ( void )
{
        DS18B20_Rst();                  
        DS18B20_Presence();                
        DS18B20_WriteByte(0X55);                /* 匹配 ROM */       
}

/*
* 存储的温度是16 位的带符号扩展的二进制补码形式
* 当工作在12位分辨率时,其中5个符号位,7个整数位,4个小数位
*
*         |---------整数----------|-----小数 分辨率 1/(2^4)=0.0625----|
* 低字节  | 2^3 | 2^2 | 2^1 | 2^0 | 2^(-1) | 2^(-2) | 2^(-3) | 2^(-4) |
*
*
*         |-----符号位:0->正  1->负-------|-----------整数-----------|
* 高字节  |  s  |  s  |  s  |  s  |    s   |   2^6  |   2^5  |   2^4  |
*
*
* 温度 = 符号位 + 整数 + 小数*0.0625
*/
/**
  * @brief  在跳过匹配 ROM 情况下获取 DS18B20 温度值
  * @param  None
  * @retval 温度值
  */
float DS18B20_GetTemp_SkipRom ( void )
{
        uint8_t tpmsb, tplsb;
        short s_tem;
        float f_tem;
       
        DS18B20_SkipRom ();
        DS18B20_WriteByte(0X44);                                /* 开始转换 */
       
        DS18B20_SkipRom ();
  DS18B20_WriteByte(0XBE);                                /* 读温度值 */
       
        tplsb = DS18B20_ReadByte();                 
        tpmsb = DS18B20_ReadByte();
       
       
        s_tem = tpmsb<<8;
        s_tem = s_tem | tplsb;
       
        if( s_tem < 0 )                /* 负温度 */
                f_tem = (~s_tem+1) * 0.0625;       
        else
                f_tem = s_tem * 0.0625;
       
        return f_tem;        
}


/**
  * @brief  在匹配 ROM 情况下获取 DS18B20 温度值
  * @param  ds18b20_id:用于存放 DS18B20 序列号的数组的首地址
  * @retval None
  */
void DS18B20_ReadId ( uint8_t * ds18b20_id )
{
        uint8_t uc;
               
        DS18B20_WriteByte(0x33);       //读取序列号
       
        for ( uc = 0; uc < 8; uc ++ )
          ds18b20_id [ uc ] = DS18B20_ReadByte();       
}

/**
  * @brief  在匹配 ROM 情况下获取 DS18B20 温度值
  * @param  ds18b20_id:存放 DS18B20 序列号的数组的首地址
  * @retval 温度值
  */
float DS18B20_GetTemp_MatchRom ( uint8_t * ds18b20_id )
{
        uint8_t tpmsb, tplsb, i;
        short s_tem;
        float f_tem;
       
       
        DS18B20_MatchRom ();            //匹配ROM
       
  for(i=0;i<8;i++)
                DS18B20_WriteByte ( ds18b20_id [ i ] );       
       
        DS18B20_WriteByte(0X44);                                /* 开始转换 */

       
        DS18B20_MatchRom ();            //匹配ROM
       
        for(i=0;i<8;i++)
                DS18B20_WriteByte ( ds18b20_id [ i ] );       
       
        DS18B20_WriteByte(0XBE);                                /* 读温度值 */
       
        tplsb = DS18B20_ReadByte();                 
        tpmsb = DS18B20_ReadByte();
       
       
        s_tem = tpmsb<<8;
        s_tem = s_tem | tplsb;
       
        if( s_tem < 0 )                /* 负温度 */
                f_tem = (~s_tem+1) * 0.0625;       
        else
                f_tem = s_tem * 0.0625;
       
        return f_tem;                
}

使用特权

评论回复
7
Wordsworth| | 2024-9-16 07:21 | 只看该作者

改变测试负载的值,再次测试输出的电流和电压

使用特权

评论回复
8
Clyde011| | 2024-9-16 08:24 | 只看该作者

表征负载能力的指标是负载能力和负载能力上升时间

使用特权

评论回复
9
公羊子丹| | 2024-9-16 09:17 | 只看该作者

环氧树脂由于硬度的原因不能用于应力敏感和含有贴片元件的模块灌封,在模块电源中基本被淘汰

使用特权

评论回复
10
万图| | 2024-9-16 10:20 | 只看该作者

直至电感器饱和,使开关器件烧毁。好的元器件就到唯样商城。图中的D3与N3构成的磁通复位电路,提供了泄放多余磁能的渠道

使用特权

评论回复
11
Uriah| | 2024-9-16 11:23 | 只看该作者

一些静态测试参数还包括波浪、纹波、起伏和静态输出电压精度。

使用特权

评论回复
12
帛灿灿| | 2024-9-16 13:19 | 只看该作者

测试参数包括电源的输出电压、输出电流、负载能力、压降、效率和输出波形

使用特权

评论回复
13
Bblythe| | 2024-9-16 14:22 | 只看该作者

逐渐变细的孔(也称为邮票孔)变得越来越普遍

使用特权

评论回复
14
周半梅| | 2024-9-16 16:18 | 只看该作者

正激:脉冲变压器的原/副边相位关系

使用特权

评论回复
15
Pulitzer| | 2024-9-16 17:21 | 只看该作者

是两根线分别对地的噪声

使用特权

评论回复
16
童雨竹| | 2024-9-16 19:17 | 只看该作者

大于1的定义为极高导热的性能,而对于模块电源此水平的导热系数是无法达到其散热功能的需求

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

85

主题

1153

帖子

0

粉丝