哈喽大家好!本篇为 STM32 嵌入式入门 Day06 学习笔记。
本节课我们重点学习 DHT11 数字温湿度传感器 ,掌握 单总线 1-Wire 通信协议 、完整时序解析、GPIO 动态输入输出切换、DHT11 驱动手写开发,最后完成综合大作业:基于 STM32 的智能温湿度监控与声光报警系统。
全文知识点细致、代码完整、逻辑清晰,适合新手学习、期末复习、CSDN 发文、面试背诵。
一、DHT11 传感器整体介绍
1.1 什么是 DHT11?
DHT11 是一款低成本、超低功耗、单总线数字式温湿度复合传感器 。内部集成湿度感应元件、温度感应元件、AD 转换电路、数字逻辑电路,直接输出数字信号,无需单片机做模数转换,极大降低开发难度。
广泛用于:智能家居、室内环境监测、仓库温湿度监控、农业大棚、设备机箱温度监测等场景。
1.2 通信方式:单总线 1-Wire
DHT11 采用标准 单总线通信协议(1-Wire):
-
仅需 一根 DATA 数据线 与 MCU 通信
-
搭配 VCC、GND 即可正常工作
-
数据线为 双向半双工通信
-
MCU 需要动态切换 GPIO 输出、输入模式,实现收发通信
单总线最大特点:一根线实现主机发、从机收、从机发、主机收。
1.3 DHT11 官方参数规格(重点考点)
| 参数类型 | 测量范围 | 测量精度/误差 | 备注 |
|---|---|---|---|
| 温度测量 | 0℃ ~ 50℃ | ±2℃ | 室内环境完全够用 |
| 湿度测量 | 10%RH ~ 90%RH | ±5%RH | RH 代表相对湿度 |
| 工作电压 | 3.3V ~ 5V | ------ | STM32 3.3V 可直接驱动 |
| 采集周期 | 最小 2S | ------ | 禁止高频采集,否则死机乱码 |
**补充知识点:**DHT11 的小数位永远为 0,精度较低;高精度项目建议使用 DHT22(AM2302)。
二、DHT11 完整通信时序(全网最细解析)
DHT11 通信严格依赖微秒级精准时序,时序错1us就会读取失败、全是0、乱码、校验错误。
完整通信四大阶段:
起始信号(MCU) → 响应信号(DHT11) → 40bit 数据传输 → 停止信号(MCU)
2.1 起始信号(主机 MCU 发起)
MCU 主动发起通信,告诉 DHT11"我要读取数据"
-
步骤1:MCU 拉低 DATA 引脚,持续 至少 18ms
-
步骤2:MCU 释放总线,拉高电平,保持 20~40us
作用:低速长拉低唤醒传感器,短暂拉高等待从机应答。
2.2 响应信号(从机 DHT11 应答)
DHT11 检测到起始信号后,返回应答握手信号:
-
步骤1:DHT11 拉低总线 80us
-
步骤2:DHT11 拉高总线 80us
握手成功后,DHT11 正式开始上传 40bit 温湿度数据。
2.3 40bit 数据帧格式(核心重点)
一次通信固定传输 40bit = 5Byte数据
数据顺序:湿度整数 + 湿度小数 + 温度整数 + 温度小数 + 校验和
| 字节序号 | 含义 | 说明 |
|---|---|---|
| Data0 | 湿度整数 | 实际有效湿度值 |
| Data1 | 湿度小数 | DHT11 固定为 0 |
| Data2 | 温度整数 | 实际有效温度值 |
| Data3 | 温度小数 | DHT11 固定为 0 |
| Data4 | 校验和 | 校验和=前4字节相加 |
2.4 位数据时序(区分 0 和 1)
每一位数据都以 50us 低电平 作为起始基准,靠高电平时长区分 0/1
逻辑 0 时序
-
拉低 50us
-
拉高 26~28us
逻辑 1 时序
-
拉低 50us
-
拉高 70us
开发黄金技巧: 等待电平跳变后 延时 45us 再读取引脚电平,低为0、高为1,时序最稳!
2.5 停止信号
-
DHT11 发送完 40bit 数据后,自动拉低总线 50us
-
MCU 主动拉高总线,结束本次通信
单次采集彻底结束,等待下一次 2S 周期采集。
三、DHT11 驱动函数架构逐行解析
硬件接线:DHT11 DATA ------> STM32 PC10
3.1 dht11_init() 初始化函数
功能:初始化 GPIO、开启时钟、默认推挽输出
-
开启 GPIOC 时钟
-
PC10 设置为推挽输出模式
-
默认高电平,等待发起通信
3.2 dht11_wait_ack() 等待应答函数
功能:切换引脚为输入模式,检测 DHT11 是否正常应答
-
PC10 改为浮空输入
-
等待从机拉低、再拉高
-
应答成功代表传感器正常在线
3.3 dht11_get_value() 数据读取核心函数
核心逻辑:循环读取 5 字节、共 40 位数据,逐位采集、拼接字节、最终解析温湿度。
-
定义 u8 data5 存储原始数据
-
循环读取每一位时序
-
45us 延时采样判断 0/1
-
最终赋值:湿度=data0,温度=data2
3.4 dht11_stop() 通信停止函数
-
恢复 PC10 为推挽输出
-
等待时序结束
-
MCU 拉高总线,结束通信
四、完整可直接编译 DHT11 驱动代码
dht11.c 驱动源码
cpp
#include "dht11.h"
#include "delay.h"
// 初始化DHT11引脚
void dht11_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_SetBits(GPIOC,GPIO_Pin_10); // 默认高电平
}
// 等待DHT11应答
u8 dht11_wait_ack(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 切换为输入模式
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStruct);
delay_us(40);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10)==0)
{
// 等待拉低结束
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10)==0);
// 等待拉高结束
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10)==1);
return 1; // 应答成功
}
return 0; // 应答失败
}
// 读取40bit数据
void dht11_get_value(u8 *temp,u8 *humi)
{
u8 data[5] = {0};
GPIO_InitTypeDef GPIO_InitStruct;
// 起始信号
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_ResetBits(GPIOC,GPIO_Pin_10);
delay_ms(20); // 拉低18ms以上
GPIO_SetBits(GPIOC,GPIO_Pin_10);
delay_us(30);
// 等待应答
if(dht11_wait_ack()==1)
{
// 循环读取5字节40位
for(int i=0;i<5;i++)
{
for(int j=0;j<8;j++)
{
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10)==0);
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10)==1);
delay_us(45);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_10))
{
data[i] |= (1<<(7-j));
}
}
}
}
// 数据赋值
*humi = data[0];
*temp = data[2];
}
五、Day06 课后大作业:智能温湿度监控与安全提醒系统
5.1 硬件设备
STM32开发板 + DHT11温湿度传感器 + LED指示灯 + 蜂鸣器 + 独立按键 + USART串口
5.2 应用场景
室内环境智能监测、仓库温湿度安全监控、设备过热低温预警、桌面智能环境助手,是非常典型的嵌入式综合实训项目。
5.3 核心功能需求(必做)
1、DHT11 定时采集功能
-
固定 2秒采集一次 温湿度数据
-
数据稳定、无乱码、无跳变
-
支持串口实时上传上位机显示
2、智能阈值报警逻辑
| 环境状态 | 判定条件 |
|---|---|
| 正常安全状态 | 10℃ ≤ 温度 ≤ 30℃ 且 湿度 ≤ 70%RH |
| 温度过高报警 | 温度 > 30℃ |
| 温度过低报警 | 温度 < 10℃ |
| 湿度过高报警 | 湿度 > 70%RH |
3、LED 分级状态指示
| LED编号 | 状态 | 系统含义 |
|---|---|---|
| LED0 | 常亮 | 环境温湿度正常,安全状态 |
| LED1 | 闪烁 | 温湿度轻微异常,预警状态 |
| LED2 | 常亮 | 温湿度严重超标,危险提醒 |
5.4 可选拓展功能(加分项)
-
蜂鸣器分级报警:预警间歇响、严重超标常响
-
按键开启/关闭报警提醒功能
-
串口实时打印温度、湿度、系统状态
-
上位机指令修改报警阈值
六、DHT11 开发高频踩坑总结(面试必背)
-
禁止高频采集:必须间隔 2S,否则传感器死机
-
GPIO 必须动态切换输入输出,单总线双向通信核心
-
延时必须精准,微秒延时不准直接读不到数据
-
必须做数据校验,防止干扰导致数据错乱
-
DHT11 小数位永远为 0,不要浪费代码解析小数
-
每次通信结束必须停止总线,复位电平状态
七、本章思考题(巩固提升)
-
DHT11 为什么需要不断切换 GPIO 输入/输出模式?
-
读取数据位时,为什么固定延时 45us 采样?
-
如果不做校验和判断,项目会出现什么问题?
-
死循环延时 2S 采集有什么弊端?如何优化?