1. 问题背景与现象描述
最近在调试DHT11温湿度传感器时遇到了一个棘手的问题:当尝试通过中断方式获取传感器数据时,系统经常出现数据读取失败或数据异常的情况。具体表现为:
- 在触发读取后,偶尔能获取到正确的温湿度数据
- 但大多数情况下要么返回全0数据,要么返回明显超出合理范围的值(如湿度120%)
- 系统日志显示中断触发时间不稳定,有时甚至没有触发中断
这个问题在多个硬件平台上都复现过,包括STM32F103和ESP8266两种常见的嵌入式开发板。使用示波器观察DHT11的数据线信号,发现传感器确实输出了完整的40位数据,但MCU端的中断服务程序似乎没有正确捕获全部数据位。
2. DHT11工作原理与通信协议解析
2.1 DHT11基本特性
DHT11是一款经典的温湿度复合传感器,采用单总线通信协议。其关键参数如下:
| 参数 | 数值范围 |
|---|---|
| 温度测量范围 | 0-50℃ (±2℃) |
| 湿度测量范围 | 20-90%RH (±5%) |
| 采样周期 | ≥1秒 |
| 供电电压 | 3.3V-5.5V |
2.2 单总线通信时序
DHT11的完整通信过程分为三个步骤:
-
主机启动信号:
- 拉低数据线至少18ms
- 然后拉高20-40μs等待传感器响应
-
传感器响应信号:
- 传感器拉低80μs作为应答
- 然后拉高80μs准备发送数据
-
数据传输阶段:
- 每bit数据以50μs低电平开始
- 高电平持续时间决定数据值:
- 26-28μs表示'0'
- 70μs表示'1'
- 共传输40位数据(16位湿度+16位温度+8位校验和)
注意:所有时间参数都有±10%的容差,实际实现时需要留有余量
3. 中断方式实现的关键问题分析
3.1 典型的中断处理实现
常见的DHT11中断处理代码结构如下:
c复制// 中断服务程序
void EXTI_IRQHandler(void) {
if(EXTI_GetITStatus(EXTI_LineX) != RESET) {
static uint32_t prev_time = 0;
uint32_t curr_time = Get_Micros();
uint32_t pulse_width = curr_time - prev_time;
// 判断脉冲宽度确定数据位
if(pulse_width > 30 && pulse_width < 70) {
// 处理数据位
}
prev_time = curr_time;
EXTI_ClearITPendingBit(EXTI_LineX);
}
}
3.2 中断方式的主要挑战
通过分析实际调试情况,发现以下几个关键问题点:
-
中断响应延迟:
- 从边沿触发到进入ISR需要一定时间(通常在1-5μs)
- 对于26-28μs的'0'信号,可能错过准确测量
-
**中
