哈喽大家好!本篇为 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数据

数据顺序:湿度整数 + 湿度小数 + 温度整数 + 温度小数 + 校验和

字节序号

含义

说明

Data[0]

湿度整数

实际有效湿度值

Data[1]

湿度小数

DHT11 固定为 0

Data[2]

温度整数

实际有效温度值

Data[3]

温度小数

DHT11 固定为 0

Data[4]

校验和

校验和=前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 data[5] 存储原始数据

  • 循环读取每一位时序

  • 45us 延时采样判断 0/1

  • 最终赋值:湿度=data[0],温度=data[2]

3.4 dht11_stop() 通信停止函数

  • 恢复 PC10 为推挽输出

  • 等待时序结束

  • MCU 拉高总线,结束通信


四、完整可直接编译 DHT11 驱动代码

dht11.c 驱动源码

#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,不要浪费代码解析小数

  • 每次通信结束必须停止总线,复位电平状态

七、本章思考题(巩固提升)

  1. DHT11 为什么需要不断切换 GPIO 输入/输出模式?

  2. 读取数据位时,为什么固定延时 45us 采样?

  3. 如果不做校验和判断,项目会出现什么问题?

  4. 死循环延时 2S 采集有什么弊端?如何优化?

Logo

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

更多推荐