news 2026/4/2 21:51:52

【mcuclub】DHT11温湿度传感器实战:从原理到代码实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【mcuclub】DHT11温湿度传感器实战:从原理到代码实现

1. DHT11温湿度传感器初探

第一次拿到DHT11这个小家伙时,我差点被它朴素的外表给骗了。这个比指甲盖大不了多少的传感器,居然能同时测量温度和湿度!它采用单总线通信协议,只需要一个GPIO引脚就能完成数据交互,特别适合那些IO资源紧张的嵌入式项目。

DHT11内部结构其实挺有意思,拆开外壳能看到两个关键元件:一个是电阻式感湿元件,负责检测环境湿度;另一个是NTC测温元件,用来测量温度。这两个元件的数据由一个8位单片机采集处理,最终输出校准后的数字信号。实测下来,它的温度测量范围是0~50℃,精度±2℃;湿度测量范围20%~90%RH,精度±5%RH。虽然比不上实验室级传感器的精度,但对于大多数智能家居、农业大棚这类应用场景完全够用。

这里有个实际使用中的小技巧:由于DHT11每次测量后都会自动进入低功耗模式,连续读取时需要间隔至少1秒,否则容易读取失败。我曾经在一个智能花盆项目里连续读取数据,就是因为没加延时导致传感器"罢工",排查了半天才发现这个问题。

2. 硬件连接与电路设计

给DHT11设计电路时,最容易被忽略的就是那个上拉电阻。因为它的数据口采用漏极开路输出,如果不接上拉电阻,信号线就只能输出低电平或高阻态,永远没法输出高电平。根据我的经验,当供电电压为5V时,接4.7KΩ的上拉电阻最稳定。如果传输距离超过20米,可以适当减小阻值。

具体接线非常简单,DHT11只有三个有效引脚(有的版本是4个引脚,但第3脚悬空):

  • VCC接3.3V-5V电源
  • GND接地
  • DATA接MCU的GPIO

这里有个硬件设计上的坑要特别注意:如果传感器距离MCU较远,建议在VCC和GND之间加个100nF的去耦电容。有次我在工业现场部署时,因为电源干扰导致数据异常,就是靠这个电容解决的。完整的参考电路如下:

[VCC 3.3V-5V] │ ┌┴┐ │ │ 4.7KΩ └┬┘ │ ├───── DATA │ === 100nF │ [GND]

3. 单总线通信协议详解

DHT11的通信协议看似简单,但时序要求非常严格。整个通信过程可以分为三个阶段:

首先是主机发送开始信号:把数据线拉低至少18ms,然后拉高20-40μs。这个阶段相当于"敲门",告诉DHT11该干活了。这里容易出错的是延时精度,普通延时函数可能不够准确,最好用定时器实现微秒级延时。

接着是传感器响应:DHT11会先拉低80μs,再拉高80μs,然后才开始传输数据。很多初学者容易在这里翻车,看到第一个低电平就急着读取数据,结果读到一堆乱码。我的经验是用中断或轮询方式严格检测这个响应信号。

最后是数据传输阶段:每个bit都以50μs低电平开始,然后高电平的持续时间决定数据是0还是1(26-28μs表示0,70μs表示1)。40bit数据包含:

  • 湿度整数(8bit) + 湿度小数(8bit)
  • 温度整数(8bit) + 温度小数(8bit)
  • 校验和(8bit)

校验和是前四个字节的和,用于验证数据正确性。我曾经遇到过校验失败的情况,后来发现是导线太长导致信号畸变,换成屏蔽线就解决了。

4. STM32驱动代码实现

下面以STM32 HAL库为例,分享一个经过实战检验的驱动代码。首先在CubeMX中配置一个GPIO引脚(如PA0)和定时器(TIM5):

// dht11.h typedef struct { uint8_t humi_int; // 湿度整数 uint8_t humi_dec; // 湿度小数 uint8_t temp_int; // 温度整数 uint8_t temp_dec; // 温度小数 uint8_t checksum; // 校验和 } DHT11_Data; uint8_t DHT11_Read(DHT11_Data *data);
// dht11.c #include "dht11.h" #include "tim.h" #define DHT11_PORT GPIOA #define DHT11_PIN GPIO_PIN_0 // 微秒级延时函数 void delay_us(uint32_t us) { __HAL_TIM_SET_COUNTER(&htim5, 0); HAL_TIM_Base_Start(&htim5); while(__HAL_TIM_GET_COUNTER(&htim5) < us); HAL_TIM_Base_Stop(&htim5); } uint8_t DHT11_Read(DHT11_Data *data) { uint8_t buf[5] = {0}; GPIO_InitTypeDef GPIO_Init = {0}; // 主机拉低18ms HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET); delay_us(18000); HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET); // 切换输入模式 GPIO_Init.Pin = DHT11_PIN; GPIO_Init.Mode = GPIO_MODE_INPUT; GPIO_Init.Pull = GPIO_PULLUP; HAL_GPIO_Init(DHT11_PORT, &GPIO_Init); // 等待传感器响应 while(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)); while(!HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)); while(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)); // 读取40bit数据 for(int i=0; i<5; i++) { for(int j=0; j<8; j++) { while(!HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)); delay_us(40); buf[i] <<= 1; if(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)) { buf[i] |= 1; while(HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN)); } } } // 校验数据 if(buf[0] + buf[1] + buf[2] + buf[3] == buf[4]) { >DHT11_Data data; if(DHT11_Read(&data)) { printf("温度: %d℃, 湿度: %d%%\n", data.temp_int, data.humi_int); }

5. 常见问题与优化技巧

在实际项目中,DHT11最常遇到三类问题:

  1. 读取失败:多数是因为时序不准确。建议用逻辑分析仪抓取波形,检查开始信号和响应信号的持续时间是否达标。有个取巧的办法是把延时时间适当加长,比如开始信号用20ms代替18ms。

  2. 数据跳变:环境变化时数据可能突变。我的解决方案是采用滑动窗口滤波:保存最近5次读数,去掉最高最低值后取平均。代码实现如下:

#define SAMPLE_SIZE 5 int filter(int new_val) { static int buf[SAMPLE_SIZE] = {0}; static int index = 0; buf[index++] = new_val; if(index >= SAMPLE_SIZE) index = 0; // 排序找最大值和最小值 int min = buf[0], max = buf[0], sum = 0; for(int i=0; i<SAMPLE_SIZE; i++) { if(buf[i] < min) min = buf[i]; if(buf[i] > max) max = buf[i]; sum += buf[i]; } return (sum - min - max) / (SAMPLE_SIZE - 2); }
  1. 长距离传输不稳定:当传感器与MCU距离超过3米时,建议:
    • 改用屏蔽线
    • 降低上拉电阻阻值(如2.2KΩ)
    • 在MCU端增加施密特触发器整形信号

对于需要更高精度的场景,可以考虑DHT22(AM2302),它的温度精度±0.5℃,湿度精度±2%RH,但价格也更高。还有个选择是SHT30,精度更高但需要I2C接口。

最后分享一个项目经验:在智能农业系统中,我把DHT11放在防水盒里,通过1米长的导线引出,每隔5分钟采集一次数据,配合LoRa模块上传云端,已经稳定运行两年多。关键是要做好防潮处理,传感器周围用硅胶密封,避免凝露影响读数。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/17 12:29:47

实测QwQ-32B:性能媲美DeepSeek的本地部署方案

实测QwQ-32B&#xff1a;性能媲美DeepSeek的本地部署方案 最近&#xff0c;阿里开源的QwQ-32B模型在技术圈引发不小关注。官方介绍中明确提到&#xff1a;它在复杂推理任务上的表现&#xff0c;已可与DeepSeek-R1、o1-mini等当前一线推理模型比肩。更关键的是——它支持本地轻…

作者头像 李华
网站建设 2026/4/1 16:52:52

SiameseUIE中文信息抽取:如何快速搭建高效的信息抽取系统

SiameseUIE中文信息抽取&#xff1a;如何快速搭建高效的信息抽取系统 在日常业务中&#xff0c;我们经常需要从大量中文文本里快速提取关键信息——比如电商评论里的产品属性和用户评价、新闻稿中的人物与事件关系、客服对话中的用户诉求和问题类型。传统方法依赖规则或标注大…

作者头像 李华
网站建设 2026/3/31 7:21:47

打造高效知识管理中心:Obsidian主页个性化配置指南

打造高效知识管理中心&#xff1a;Obsidian主页个性化配置指南 【免费下载链接】obsidian-homepage Obsidian homepage - Minimal and aesthetic template (with my unique features) 项目地址: https://gitcode.com/gh_mirrors/obs/obsidian-homepage Obsidian自定义界…

作者头像 李华
网站建设 2026/3/16 23:00:13

Windows预览体验计划退出方案:技术原理与实施指南

Windows预览体验计划退出方案&#xff1a;技术原理与实施指南 【免费下载链接】offlineinsiderenroll 项目地址: https://gitcode.com/gh_mirrors/of/offlineinsiderenroll 问题诊断&#xff1a;预览版系统稳定性问题的技术分析 Windows预览体验计划&#xff08;Windo…

作者头像 李华
网站建设 2026/4/1 2:55:13

EagleEye实操手册:EagleEye检测结果JSON Schema解析与结构化入库方案

EagleEye实操手册&#xff1a;EagleEye检测结果JSON Schema解析与结构化入库方案 1. 为什么需要解析EagleEye的JSON输出&#xff1f; 你刚跑通EagleEye&#xff0c;上传一张图&#xff0c;几毫秒后右侧面板弹出带框的识别结果——很酷。但如果你真正想用它做点实事&#xff0…

作者头像 李华