一、DHT11传感器概述

DHT11是一款非常经典的数字温湿度传感器,由广州奥松电子研发。它内部集成了一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连,直接输出已校准的数字信号。每个DHT11传感器出厂前都在精密的湿度校验室中进行校准,校准系数以程序形式储存在OTP内存中。

核心参数

参数 规格
供电电压 3V ~ 5.5V
温度测量范围 0℃ ~ 50℃,精度 ±2℃
湿度测量范围 20% ~ 90% RH,精度 ±5% RH
采样周期 ≥1秒/次
待机电流 0.06mA,测量电流1.0mA

信号传输距离可达20米以上,具有抗干扰能力强、性价比高等优点。

引脚说明

DHT11采用4针单排引脚封装:

  • VCC引脚:电源正极,接单片机3.3V或5V

  • GND引脚:电源负极,接单片机GND

  • DAT引脚:单总线数据引脚,接单片机P1.2(或任意I/O口)

  • NC引脚:空脚,不接

二、硬件电路设计

2.1 上拉电阻

DHT11采用漏极开路输出,因此数据线必须外接上拉电阻,使得总线空闲时保持高电平。

上拉电阻的阻值选择建议:

  • 连接线长度 < 20米:使用 5kΩ 上拉电阻

  • 连接线长度 > 20米:根据实际情况选择合适阻值

在代码对应的硬件中,main.h里定义了数据引脚:

sbit DHT11_IO = P1^2;

2.2 电源去耦

传感器上电后,需要等待约1秒以越过不稳定状态。为了提高稳定性,建议在VDD和GND之间并联一个100nF的陶瓷电容,用于滤除电源噪声。

2.3 硬件连接总结

DHT11引脚 连接目标
VCC 单片机3.3V或5V
GND 单片机GND
DAT 单片机P1.2(通过5kΩ上拉电阻接VCC)

三、单总线通信协议详解

3.1 什么是单总线(1-Wire)

DHT11采用简化的单总线通信方式。单总线即只有一根数据线,系统中的数据交换、控制均由这一根线完成。设备通过漏极开路或三态端口连接至数据线,在不发送数据时释放总线。

总线空闲状态为高电平。整个通信过程是主从结构,只有主机(单片机)呼叫从机(DHT11)时,从机才能应答。

3.2 通信过程概览

一次完整的通信过程如下图所示:

整个过程分为三个主要阶段:

  1. 开始信号:主机拉低总线,发起通信

  2. 数据传输:DHT11发送40位数据

  3. 结束信号:总线恢复高电平,进入空闲状态

3.3 第一阶段:开始信号

步骤1:主机拉低总线(至少18ms)

主机(单片机)先将数据线拉低,持续至少18ms的低电平。代码实现为:

DHT11_IO = 0;
Delay_xms(20);  // 拉低20ms,超过18ms的最低要求

步骤2:主机拉高总线(20-40μs)

主机拉高总线,持续20-40μs

DHT11_IO = 1;
Delay30us();  // 拉高约30μs

步骤3:DHT11响应(80μs低电平 + 80μs高电平)

DHT11检测到开始信号结束后,会发送响应信号:

  • 先拉低总线 80μs,作为应答

  • 再拉高总线 80μs,准备发送数据

代码通过循环检测总线状态来确认响应:

while(!DHT11_IO && count < 80)  // 等待DHT11拉低(响应低电平)
{
    _nop_();
    count++;
}
while(DHT11_IO && count < 80)   // 等待DHT11拉高(响应高电平)
{
    _nop_();
    count++;
}

如果检测到响应信号异常(超时),函数返回错误。

3.4 第二阶段:数据传输(40位)

握手成功后,DHT11开始传送40位数据。

数据格式

40位数据的格式为:

字节 内容
第1字节(8bit) 湿度整数数据
第2字节(8bit) 湿度小数数据(通常为0)
第3字节(8bit) 温度整数数据
第4字节(8bit) 温度小数数据(通常为0)
第5字节(8bit) 校验和

高位先出(MSB First)。

校验和

校验和数据等于前四个字节相加所得结果的末8位

校验和 = (湿度整数 + 湿度小数 + 温度整数 + 温度小数) & 0xFF

代码的校验逻辑:

if(dht_buf[0] + dht_buf[1] + dht_buf[2] + dht_buf[3] == dht_buf[4])
{
    *humi = dht_buf[0];
    *temp = dht_buf[2];
}

如果校验和不匹配,说明数据传输有误,函数返回错误。

每一位数据的传输方式

每一位数据都以50μs的低电平开始。随后是高电平,高电平的持续时间决定了该位是0还是1:

  • 数据 '0':高电平持续 26-28μs

  • 数据 '1':高电平持续 70μs

代码读取一个位的实现:

while(!DHT11_IO && count < 80)  // 等待50μs低电平结束
{
    _nop_();
    count++;
}

Delay30us();  // 延时约30μs

if(1 == DHT11_IO)  // 如果30μs后仍然是高电平 → 数据'1'
{
    data_bit = 1;
    while(DHT11_IO && count < 80)  // 等待高电平结束
    {
        _nop_();
        count++;
    }
}
else  // 30μs后已经是低电平 → 数据'0'
{
    data_bit = 0;
}

这里的关键技巧是:延时30μs后检测电平——如果还是高电平,说明高电平至少持续了30μs,必然是数据'1'(因为数据'0'的高电平只持续26-28μs,30μs后已经变低了)。

3.5 第三阶段:结束信号

当最后一位数据传送完毕后,DHT11会拉低总线50μs,随后总线被上拉电阻拉高,进入空闲状态。

3.6 采样频率

DHT11的采样周期必须 ≥ 1秒。如果采集频率过高,传感器可能来不及完成新的测量,导致数据不准确。代码通过tim_count实现了1秒采集一次:

if(tim_count == 0)
{
    if(1 == DHT11_Read(&humity, &temperature))
    {
        // 读取失败
    }
    else
    {
        // 显示数据
    }
}
tim_count++;
tim_count = tim_count % 1000;
Delay_xms(1);  // 每1ms累加一次,1000次正好1秒

四、代码实现解析

4.1 工程结构

项目采用模块化设计:

文件 功能
main.c 主程序,OLED显示控制
dht11.c/h DHT11驱动程序
delay.c/h 延时函数
iic.c/h IIC通信(用于OLED)
oled.c/h OLED显示驱动
uart.c/h 串口通信

4.2 DHT11驱动核心函数

DHT11_Start():发送开始信号并等待响应

DHT11_Read():读取40位数据,进行校验,返回温湿度值

4.3 延时函数的精确性

单总线通信对时序精度要求很高。代码针对11.0592MHz晶振设计了精确延时:

void Delay30us(void)  // @11.0592MHz
{
    unsigned char data i;
    i = 11;
    while (--i);
}

Delay30us()通过11次循环实现约30μs的延时,用于判断数据位是0还是1。

Delay_xms(20)实现20ms的延时,满足开始信号≥18ms的要求。

4.4 OLED显示

代码使用OLED显示屏显示温湿度数据:

OLED_ShowCHinese(0,0,0);   // 温
OLED_ShowCHinese(18,0,1);  // 湿
OLED_ShowCHinese(36,0,2);  // 度
OLED_ShowCHinese(54,0,3);  // 检
OLED_ShowCHinese(72,0,4);  // 测
OLED_ShowCHinese(90,0,5);  // 系
OLED_ShowCHinese(108,0,6); // 统

sprintf(buf,"H:%u%% T:%uC", (uint)humity, (uint)temperature);
OLED_ShowString(0,4,buf,16);

显示效果为"温湿度检测系统"标题,下方显示"H:xx% T:xxC"。

五、常见问题与调试技巧

5.1 读取失败(返回1)

可能的原因:

  1. 接线错误:检查VCC、GND、DAT是否连接正确

  2. 上拉电阻缺失:DAT引脚必须接上拉电阻

  3. 时序不匹配:晶振频率不同导致延时不准

  4. 电源不稳定:添加100nF去耦电容

5.2 数据跳变或异常

  1. 采样频率过快:确保采集间隔≥1秒

  2. 电源噪声:检查电源质量,靠近传感器放置去耦电容

  3. 总线干扰:数据线尽量短,远离高频信号源

5.3 调试建议

  1. 使用逻辑分析仪示波器抓取总线波形,验证时序

  2. 通过串口输出原始数据,观察校验和是否正确

  3. 在关键位置添加LED指示,便于观察程序运行状态

六、总结

DHT11的单总线通信虽然协议简单,但对时序要求严格。理解其通信的三个阶段——开始信号、数据传输(40位)、结束信号——是成功驱动的关键。通过精确的延时控制和数据校验机制,我们可以在51单片机上稳定地读取温湿度数据。

完整的代码工程已开源,包含了DHT11驱动、OLED显示、串口输出等功能模块,可作为学习单总线通信和嵌入式开发的参考项目。

Logo

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

更多推荐