STM32基于HAL工程FREERTOS读取DS18B20数据+串口输出


  • ✨申明:本文章仅发表在CSDN网站,任何其他网站,未注明来源,见此内容均为盗链和爬取,请多多尊重和支持原创!
  • 🍁对于文中所提供的相关资源链接将作不定期更换。
🔰基于STM32CubeMX配置工程,当然不局限于STM32其他型号的芯片的使用,只要是stm32芯片都可以使用该源文件进行驱动,方便适配移植,减少不必要的重复开发工作。
  • 🎯本工程经实物验证,程序没有问题。
  • 🔖工程基于FREERTOS下,串口打印读取到数据,
    在这里插入图片描述

🛠STM32F103基于STM32CubeMX配置工程

  • 🔨配置FREERTOS时基。(OS的时基和 SysTick(滴答定时器) 分开)
    在这里插入图片描述
  • 🌿开启定时器1用于读取DS18B20数据时使用。
    在这里插入图片描述
  • 🌿配置DS18B20数据引脚
    在这里插入图片描述
  • 🌿使能一个串口,用于调试信息输出
    在这里插入图片描述
  • 🧲在中间件(Middleware)当中,选择OS系统
    在这里插入图片描述
  • 🌿根据实际运行情况适当调整堆栈空间。
    在这里插入图片描述
📚工程源码
链接: https://pan.baidu.com/s/1hphH64UK_BsM9nSOL-0FJQ
提取码: wzb1

DS18B20传感器温度读取流程

DS18B20是单总线数字温度传感器,移植其驱动核心是实现单总线时序(复位、存在脉冲、写位、读位),再基于时序封装温度读取逻辑。以下以STM32为例(裸机,基于HAL库),讲解通用移植步骤和核心代码。

一、硬件准备与引脚配置
  1. 硬件连接
    • DS18B20的VDD接3.3V(或5V,注意电平匹配);
    • GND接单片机GND;
    • DQ(数据引脚)接单片机任意GPIO(如PA0),并串联4.7K上拉电阻到VDD。
  2. GPIO配置(STM32 HAL库):
    • 模式:推挽输出 + 上拉输入(需动态切换输入/输出);
    • 速度:低速即可。
二、核心:单总线时序实现(关键)

DS18B20的所有通信依赖严格的单总线时序,这是移植的核心,不同MCU(如STM32、51、GD32)仅GPIO操作不同,时序逻辑完全一致。

1. 引脚电平操作封装(适配不同MCU)

先封装GPIO的输入/输出切换、电平读写,方便移植到其他MCU时仅修改此处:

#include "stm32f1xx_hal.h"

// 定义DS18B20数据引脚(根据实际硬件修改)
#define DS18B20_DQ_PORT    GPIOA
#define DS18B20_DQ_PIN     GPIO_PIN_0

// 设置DQ为输出模式
static void DS18B20_Set_Output(void)
{
    GPIO_InitTypeDef gpio_init_struct = {0};
    gpio_init_struct.Pin = DS18B20_DQ_PIN;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;  // 推挽输出
    gpio_init_struct.Pull = GPIO_NOPULL;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(DS18B20_DQ_PORT, &gpio_init_struct);
}

// 设置DQ为输入模式
static void DS18B20_Set_Input(void)
{
    GPIO_InitTypeDef gpio_init_struct = {0};
    gpio_init_struct.Pin = DS18B20_DQ_PIN;
    gpio_init_struct.Mode = GPIO_MODE_INPUT;     // 输入模式(上拉由硬件电阻保证)
    gpio_init_struct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(DS18B20_DQ_PORT, &gpio_init_struct);
}

// 写DQ引脚电平
static void DS18B20_Write_Level(uint8_t level)
{
    if(level)
        HAL_GPIO_WritePin(DS18B20_DQ_PORT, DS18B20_DQ_PIN, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(DS18B20_DQ_PORT, DS18B20_DQ_PIN, GPIO_PIN_RESET);
}

// 读DQ引脚电平
static uint8_t DS18B20_Read_Level(void)
{
    return HAL_GPIO_ReadPin(DS18B20_DQ_PORT, DS18B20_DQ_PIN);
}

// 微秒级延时(需根据MCU主频校准,STM32F1默认72MHz)
static void DS18B20_Delay_Us(uint16_t us)
{
    uint32_t ticks = (HAL_RCC_GetHCLKFreq() / 1000000) * us;
    ticks /= 8;  // 简易延时,需实际校准
    while(ticks--);
}
2. 单总线核心时序实现
(1)复位与检测脉冲
uint8_t DS18B20_Reset(void)
{
    uint8_t retry = 0;
    DS18B20_Set_Output();  // 输出模式
    DS18B20_Write_Level(0); // 拉低总线至少480us
    DS18B20_Delay_Us(500);
    
    DS18B20_Write_Level(1); // 释放总线,等待15~60us
    DS18B20_Set_Input();    // 切换为输入模式
    DS18B20_Delay_Us(60);
    
    // 检测DS18B20的存在脉冲(拉低总线60~240us)
    while(DS18B20_Read_Level() && retry < 100)
    {
        retry++;
        DS18B20_Delay_Us(1);
    }
    if(retry >= 100)
        return 1; // 复位失败
    else
        retry = 0;
    
    // 等待存在脉冲结束(总线恢复高电平)
    while(!DS18B20_Read_Level() && retry < 200)
    {
        retry++;
        DS18B20_Delay_Us(1);
    }
    DS18B20_Set_Output(); // 恢复输出模式
    return 0; // 复位成功
}
(2)写位时序
void DS18B20_Write_Bit(uint8_t bit)
{
    DS18B20_Set_Output();
    DS18B20_Write_Level(0); // 拉低总线至少1us
    DS18B20_Delay_Us(2);
    
    // 写1:释放总线;写0:保持拉低
    if(bit)
        DS18B20_Write_Level(1);
    else
        DS18B20_Write_Level(0);
    
    DS18B20_Delay_Us(60); // 保持时序至少60us
    DS18B20_Write_Level(1); // 释放总线
    DS18B20_Delay_Us(2);
}
(3)读位时序
uint8_t DS18B20_Read_Bit(void)
{
    uint8_t bit = 0;
    DS18B20_Set_Output();
    DS18B20_Write_Level(0); // 拉低总线至少1us
    DS18B20_Delay_Us(2);
    
    DS18B20_Write_Level(1); // 释放总线
    DS18B20_Set_Input();    // 切换输入模式
    DS18B20_Delay_Us(10);   // 等待数据稳定
    
    // 读取总线电平(DS18B20在15us内输出数据)
    if(DS18B20_Read_Level())
        bit = 1;
    else
        bit = 0;
    
    DS18B20_Delay_Us(50); // 等待时序结束
    DS18B20_Set_Output(); // 恢复输出模式
    return bit;
}
(4)写字节/读字节封装
// 写字节(低位先行)
void DS18B20_Write_Byte(uint8_t byte)
{
    uint8_t i;
    for(i=0; i<8; i++)
    {
        DS18B20_Write_Bit(byte & 0x01);
        byte >>= 1;
    }
}

// 读字节(低位先行)
uint8_t DS18B20_Read_Byte(void)
{
    uint8_t i, byte = 0;
    for(i=0; i<8; i++)
    {
        byte >>= 1;
        if(DS18B20_Read_Bit())
            byte |= 0x80;
    }
    return byte;
}
三、温度读取逻辑封装

DS18B20读取温度的流程:复位 → 发送跳过ROM指令(0xCC)→ 发送转换指令(0x44)→ 等待转换完成 → 复位 → 发送跳过ROM指令 → 发送读暂存器指令(0xBE)→ 读取2字节温度数据 → 转换为实际温度。

// 读取DS18B20温度(返回值:0成功,1失败;temp为温度指针,单位℃,保留1位小数)
uint8_t DS18B20_Read_Temperature(float *temp)
{
    uint8_t temp_h, temp_l;
    uint16_t temp_raw;
    
    if(DS18B20_Reset() != 0) // 复位失败
        return 1;
    
    DS18B20_Write_Byte(0xCC); // 跳过ROM指令(单传感器时用)
    DS18B20_Write_Byte(0x44); // 启动温度转换
    DS18B20_Delay_Us(10);     // 无需等待,可轮询或延时(转换需约750ms)
    
    // 等待转换完成(简易方式:延时750ms,也可检测总线电平)
    HAL_Delay(750);
    
    if(DS18B20_Reset() != 0) // 再次复位
        return 1;
    
    DS18B20_Write_Byte(0xCC); // 跳过ROM指令
    DS18B20_Write_Byte(0xBE); // 读暂存器指令
    
    // 读取温度低字节、高字节(共16位)
    temp_l = DS18B20_Read_Byte();
    temp_h = DS18B20_Read_Byte();
    
    // 组合原始温度值(DS18B20温度格式:高5位符号位,低11位数据位)
    temp_raw = (temp_h << 8) | temp_l;
    
    // 转换为实际温度(分辨率12位时,1LSB=0.0625℃)
    if(temp_raw & 0x8000) // 负温度
    {
        temp_raw = ~temp_raw + 1; // 补码转原码
        *temp = -((float)temp_raw * 0.0625);
    }
    else // 正温度
    {
        *temp = (float)temp_raw * 0.0625;
    }
    
    return 0;
}
四、移植适配要点(关键!)
  1. 延时校准DS18B20_Delay_Us是时序核心,不同MCU(如51、STM32H7、ESP32)的微秒延时实现不同,需用逻辑分析仪/示波器校准,确保:
    • 复位拉低≥480us;
    • 写位拉低≥1us,总时序≥60us;
    • 读位拉低≥1us,10us后读取数据。
  2. 多传感器适配:若总线上有多个DS18B20,需替换“跳过ROM指令(0xCC)”为“匹配ROM指令(0x55)+ 传感器64位ROM地址”。
  3. 电平匹配:若MCU是3.3V、DS18B20接5V,需加电平转换(如三极管、MOS管),避免GPIO过压。
  4. 初始化调用:在主函数中先初始化GPIO时钟,再调用DS18B20_Reset()检测传感器。
五、测试代码(主函数示例)
int main(void)
{
    float temp;
    HAL_Init();
    SystemClock_Config(); // 初始化系统时钟(STM32标准流程)
    MX_GPIO_Init();       // 初始化GPIO(包含DS18B20引脚)
    
    while(1)
    {
        if(DS18B20_Read_Temperature(&temp) == 0)
        {
            // 打印温度(如串口输出,示例:temp=25.5℃)
            printf("Temperature: %.1f℃\r\n", temp);
        }
        else
        {
            printf("DS18B20 read failed!\r\n");
        }
        HAL_Delay(1000); // 1秒读取一次
    }
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐