news 2026/5/14 14:14:23

STM32F103ZET6驱动DHT11温湿度传感器,串口打印数据保姆级教程(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32F103ZET6驱动DHT11温湿度传感器,串口打印数据保姆级教程(附完整代码)

STM32F103ZET6驱动DHT11温湿度传感器实战指南:从原理到代码调试

第一次拿到DHT11温湿度传感器模块时,我盯着那根单总线接口陷入了沉思——这么简单的物理连接,为什么实际编程时总会遇到各种时序问题?经过三个项目的反复调试,终于摸清了这套系统的运作规律。本文将用最直白的方式,带你从零开始构建完整的DHT11驱动方案。

1. 硬件准备与环境搭建

手边需要准备以下硬件组件:

  • STM32F103ZET6最小系统板(兼容Blue Pill开发板)
  • DHT11温湿度传感器模块(注意选择3.3V版本)
  • 4.7K上拉电阻
  • USB转TTL串口模块(如CH340G)
  • 杜邦线若干

接线示意图

设备引脚STM32对应引脚
DHT11 VCC3.3V
DHT11 GNDGND
DHT11 DATAPB11
USB-TTL RXPA9 (USART1)
USB-TTL TXPA10 (USART1)

注意:DHT11的DATA线必须接4.7K上拉电阻到3.3V,这是稳定通信的关键

在STM32CubeMX中按以下步骤初始化:

  1. 选择STM32F103ZE系列芯片
  2. 配置RCC:HSE晶振模式
  3. 配置SYS:Serial Wire调试接口
  4. 配置USART1:异步模式,115200波特率
  5. 配置PB11为GPIO_Output(初始状态设为高电平)
// 生成的GPIO初始化代码片段 GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);

2. DHT11通信协议深度解析

DHT11采用单总线协议,其通信过程可分为四个阶段:

  1. 主机启动信号

    • 拉低总线至少18ms
    • 释放总线并延时20-40us
    • 等待从机响应
  2. 从机响应信号

    • 从机拉低总线80us
    • 从机拉高总线80us
    • 开始传输数据
  3. 数据传输格式

    • 每bit以50us低电平开始
    • 高电平持续时间决定数据值:
      • 26-28us表示'0'
      • 70us表示'1'
    • 完整数据包包含5字节(40bit)
  4. 数据校验机制

    • 前4字节求和应与第5字节(校验和)相等
    • 校验失败需重新读取

典型问题排查表

现象可能原因解决方案
无响应上拉电阻缺失添加4.7K上拉电阻
数据校验失败时序不精确调整延时函数精度
温度值异常电源干扰增加0.1uF去耦电容
偶尔读取失败两次读取间隔不足保持至少1秒的读取间隔

3. 关键代码实现与优化

完整的驱动代码需要处理三个核心环节:

3.1 起始信号生成

void DHT11_Start(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; // 设置为输出模式 GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 拉低18ms HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); HAL_Delay(20); // 实际18ms即可,增加冗余 // 释放总线 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); delay_us(30); // 精确延时20-40us }

3.2 数据位读取优化

传统轮询方式存在时间误差,改用定时器捕获更可靠:

uint8_t DHT11_ReadBit(void) { uint8_t cnt = 0; while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_RESET); // 使用SysTick做精确计时 uint32_t start = HAL_GetTick(); while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11) == GPIO_PIN_SET) { cnt++; delay_us(1); if(cnt > 100) break; // 超时保护 } return (cnt > 50) ? 1 : 0; // 阈值设为50us }

3.3 完整数据包处理

uint8_t DHT11_ReadData(float *temperature, float *humidity) { uint8_t buf[5] = {0}; uint8_t i, j; DHT11_Start(); if(DHT11_Check() == 0) { for(i=0; i<5; i++) { for(j=0; j<8; j++) { buf[i] <<= 1; buf[i] |= DHT11_ReadBit(); } } // 校验数据 if(buf[4] == (buf[0]+buf[1]+buf[2]+buf[3])) { *humidity = buf[0] + buf[1]*0.1; *temperature = buf[2] + buf[3]*0.1; return 1; } } return 0; }

4. 调试技巧与性能提升

4.1 逻辑分析仪实战应用

使用Saleae逻辑分析仪捕获的典型波形:

  1. 配置采样率至少4MHz
  2. 添加协议解码器(自定义单总线协议)
  3. 关键测量点:
    • 起始信号下降沿到上升沿时间
    • 从机响应低电平持续时间
    • 数据位高电平脉宽

调试中发现:当环境温度超过30℃时,DHT11的高电平持续时间会缩短约5us,需要在代码中动态调整判断阈值

4.2 低功耗优化方案

对于电池供电场景:

  1. 在两次读取之间将PB11设为模拟输入模式
  2. 添加硬件开关控制DHT11电源
  3. 使用停机模式+外部中断唤醒
void Enter_LowPowerMode(void) { // 切换为模拟输入减少功耗 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 配置唤醒中断 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); }

4.3 抗干扰设计要点

  • 电源端并联100nF+10uF电容
  • 数据线走线长度不超过20cm
  • 避免与电机等大电流设备共用电源
  • 在恶劣环境中可增加TVS二极管保护

实际项目中,通过以下代码增强鲁棒性:

uint8_t DHT11_AutoRetry(uint8_t retries, float *temp, *humi) { while(retries--) { if(DHT11_ReadData(temp, humi)) { return 1; } HAL_Delay(1500); // 必须大于1秒间隔 } return 0; }

5. 项目进阶与扩展思考

掌握了基础驱动后,可以尝试以下扩展方向:

  1. 多传感器组网

    • 使用IO扩展器连接多个DHT11
    • 采用时分复用策略轮流读取
    • 示例电路:
      [MCU] -- [74HC595] -- [DHT11阵列] | +-- 4.7K上拉
  2. 数据持久化存储

    • 搭配SPI Flash存储历史数据
    • 设计环形缓冲区结构
    • 添加时间戳(需要RTC支持)
  3. 无线传输方案

    • 通过HC-05蓝牙模块传输数据
    • 使用ESP8266实现WiFi上传
    • 低功耗LoRa远距离传输

在最近的一个温室监控项目中,我们将DHT11与土壤湿度传感器组合使用,发现当两者数据出现矛盾时(高湿度但土壤干燥),往往是DHT11结露导致。最终通过增加简单的数据融合算法解决了这个问题:

float Get_AdjustedHumidity(void) { float dht_humi, soil_humi; DHT11_ReadData(NULL, &dht_humi); soil_humi = Read_SoilSensor(); // 当差异大于15%时采用土壤传感器数据 if(fabs(dht_humi - soil_humi) > 15.0) { return soil_humi * 1.2; // 经验系数 } return dht_humi; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/14 14:14:22

超越Burp自带历史记录:Logger++插件在API安全测试中的3个高级用法

超越Burp自带历史记录&#xff1a;Logger插件在API安全测试中的3个高级用法 在API安全测试领域&#xff0c;Burp Suite无疑是渗透测试工程师的标配工具。然而&#xff0c;随着前后端分离架构和微服务化的普及&#xff0c;传统Web应用测试中简单的请求/响应记录已无法满足复杂AP…

作者头像 李华
网站建设 2026/5/14 14:12:08

如何快速构建智能图像篡改检测系统:3步实战指南

如何快速构建智能图像篡改检测系统&#xff1a;3步实战指南 【免费下载链接】image_tampering_detection_references A list of papers, codes and other interesting collections pertaining to image tampering detection and localization. 项目地址: https://gitcode.com…

作者头像 李华
网站建设 2026/5/14 14:10:06

如何高效拆分CATIA多实体零件:pycatia自动化解决方案的完整指南

如何高效拆分CATIA多实体零件&#xff1a;pycatia自动化解决方案的完整指南 【免费下载链接】pycatia python module for CATIA V5 automation 项目地址: https://gitcode.com/gh_mirrors/py/pycatia 在CATIA三维设计领域&#xff0c;工程师们经常面临一个常见挑战&…

作者头像 李华
网站建设 2026/5/14 14:09:05

在计算机网络中IP地址的最小单元

如你所知&#xff0c;在计算机网络中&#xff0c;使用一种寻址系统来区分不同的计算机&#xff0c;就像房子有一个地址&#xff0c;这样邮递员才可以投递信件。街道地址在互联网上就相当于 IP 地址。每台计算机都被分配一个唯一的 IP 地址。IP 地址并不是网络寻址系统中最小的单…

作者头像 李华