跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C

STM32 DHT11 温湿度传感器驱动与通信协议解析

介绍 DHT11 温湿度传感器特性及 STM32 驱动实现。涵盖电气参数、引脚定义、单总线通信协议与时序分析。提供基于寄存器的 C 语言驱动代码,包括初始化、读写函数及主程序逻辑,演示通过串口输出温湿度数据的方法。

CloudNative发布于 2026/3/22更新于 2026/5/2324 浏览
STM32 DHT11 温湿度传感器驱动与通信协议解析

一、DHT11 概述

DHT11 是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电容式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。

DHT11 温湿度传感器应用广泛,常见于暖通空调、除湿器、农业、冷链仓储、测试及检测设备、消费品、汽车、自动控制、数据记录器、气象站、家电、湿度调节器、医疗、其他相关湿度检测控制。

DHT11 具有成本低、长期稳定、相对湿度和温度测量、品质卓越、超快响应、抗干扰能力强、超长的信号传输距离、数字信号输出、精确校准等优点。

文章配图

二、相关参数

2.1 电气特性

文章配图

使用时一定要注意 DHT11 的供电电压范围,尽可能处于给定范围之间,避免电压过低或过高影响测量效果。

2.2 引脚说明

1、VDD 供电 3.3~5.5VDC

2、DATA 串行数据,单总线

3、NC 空脚(通常不引出)

4、GND 接地,电源负极

2.3 温湿度测试性能

文章配图

可见,DHT11 的相对湿度测量范围是 5~95 %RH。其中在温度为 25℃时,精度±5 %RH 等。

文章配图

可见,DHT11 的温度测量范围是 -20~60℃,其中在温度为 25℃时,±2℃的浮动范围等。

三、通信方式(单线双向)

3.1 DHT11 简化单总线协议说明

手册上写的已经非常详细了,这里就不再赘述,直接上截图了,相信大家也能理解,如下图所示。

文章配图

3.2 DHT11 单总线数据格式

文章配图

3.3 DHT11 通信时序说明

如下图为 DHT11 与微控制器 (主设备) 进行通信时的数据时序图。

文章配图

文章配图

3.4 主从通信步骤

主机和从机之间的通信可通过如下几个步骤完成(外设(如微处理器)读取 DHT11 的数据的步骤)。

1、DHT11 上电后等待 1s 稳定后处于输入状态,检测外部信号,此时总线空闲,默认拉高;

2、主机获取总线控制权,并拉低总线 18~30ms,随后释放总线。总线空闲,默认拉高;

3、DHT11 占据总线,拉低总线 83us,产生应答;接着拉高总线 87us,提示主机准备接收数据;

此时,对于主机来说,即检测总线是否拉低判断 DHT11 是否产生应答,接着若应答了,则继续等待 DHT1 应答信号结束,接着等待 DHT11 的拉高结束,完成响应信号的时序。

4、DHT 继续占据总线,开始连续发送 40 位数据。发送数据'0',DHT11 先拉低总线 54us,再拉高总线 2327us;发送数据"1",DHT11 先拉低总线 54us,再拉低总线 6874us,连续重复 40 次;

对于主机来说,即读取每一位数据,连续 8 次进而读取一字节数据,连续读取 5 次字节数据进而获取完整 40 位数据。所以理解读取一位数据的方法即可以此类推。

这个过程为:读取总线电平,等待总线拉低完成,接着延迟 30us 越过出现数据 0 的时序(便于同时进行数据 0 或 1 的接收),然后读取总线电平,若为低说明此时 DHT11 发送的确实是数据"1",反之发送的是数据"0",最后若为数据 1 则继续等待总线拉高完成,反之则一位数据读取结束。

5、DHT11 发送完 40 位数据后,会先拉低总线 54us 后自动释放总线,使总线空闲,默认拉高。

此时 DHT11 释放总线后,总线会处于空闲状态,此时需要等待 DHT11 内部重测温湿度数据并记录。故DHT11 产生停止信号后主机不必恢复占据空闲的总线,影响 DHT11 的数据记录以及后续的通信。此时让总线空闲,自由时序即可。

最后,主机记录好 40 位数据,并进行校验,没有问题说明接受的数据无误,串口输出数据即可。

3.5 注意事项

文章配图

四、参考代码 (基于 STM32)

最后,我们基于 STM32 的寄存器方式编写一下 DHT11 的驱动代码,实现串口打印温湿度数据。

4.1 DHT11 驱动代码

1、dht11.h
/* @Descripttion: DHT11 驱动程序(寄存器方式) */
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
#include "usart.h"
#include "Delay.h"

// 数据线状态
#define DHT11_SDA_HIGH() {GPIOA->BSRR |= GPIO_BSRR_BR5;} // 拉高
#define DHT11_SDA_LOW() {GPIOA->BRR |= GPIO_BRR_BR5;}   // 拉低

// 读数据
#define DHT11_READ (GPIOA->IDR & GPIO_IDR_IDR5) // 读电平

// 应答与非应答
#define ACK 0
#define NACK 1

// 输入输出模式
typedef enum {
    INPUT_MODE = 1,
    OUTPUT_MODE
}IOMode;

// 函数声明
void DHT11_Init(void);
void DHT11_SetIOMode(IOMode mode);
void DHT11_Start(void);
int8_t DHT11_Wait4Ack(void);
int8_t DHT11_ReadBit(void);
int8_t DHT11_ReadByte(void);
uint8_t DHT11_GetHumTemp(uint8_t *buffer);

#endif
2、dht11.c
/* @Descripttion: DHT11 驱动程序(寄存器方式) */
#include "dht11.h"

/**
 * @brief DHT11 初始化函数
 * @return None
 */
void DHT11_Init(void) {
    // 开漏输出 PA5 mode-11 cnf-01
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    GPIOA->CRL |= GPIO_CRL_MODE5;
    GPIOA->CRL &= ~GPIO_CRL_CNF5_1;
    GPIOA->CRL |= GPIO_CRL_CNF5_0;
    DHT11_SDA_HIGH();
}

/**
 * @brief 设置 DHT11 引脚模式
 * @param mode: 输入模式或输出模式
 * @return None
 */
void DHT11_SetIOMode(IOMode mode) {
    switch (mode) {
        case INPUT_MODE:
            // 浮空输入
            GPIOA->CRL &= ~(GPIO_CRL_MODE5 | GPIO_CRL_CNF5_1);
            GPIOA->CRL |= GPIO_CRL_CNF5_0;
            break;
        case OUTPUT_MODE:
            // 开漏输出
            GPIOA->CRL |= GPIO_CRL_MODE5;
            GPIOA->CRL &= ~GPIO_CRL_CNF5_1;
            GPIOA->CRL |= GPIO_CRL_CNF5_0;
            break;
        default:
            break;
    }
}

/**
 * @brief 发送起始信号
 * @return None
 */
void DHT11_Start(void) {
    // 1. 主机占用总线
    DHT11_SetIOMode(OUTPUT_MODE);
    // 2. SDA 拉低,发出起始信号
    DHT11_SDA_LOW();
    Delay_ms(20);
    // 3. 主机释放总线
    DHT11_SDA_HIGH();
    DHT11_SetIOMode(INPUT_MODE);
    Delay_us(20);
}

/**
 * @brief 等待 DHT11 响应
 * @return ACK 表示成功,NACK 表示失败
 * @attention 利用循环等待结束,避免延时超过或提前造成时序差错
 */
int8_t DHT11_Wait4Ack(void) {
    // 1. 出现应答信号
    if (!DHT11_READ) {
        // 2. 等待 DHT11 拉低应答完成
        while (!DHT11_READ);
        // 3. 等待 DHT11 拉高完成,准备接收数据
        while (DHT11_READ);
        return ACK;
    }
    return NACK;
}

/**
 * @brief 读取一个位的数据
 * @return 读取到的位值 (0 或 1)
 * @attention 利用循环等待结束,避免延时超过或提前造成时序差错
 */
int8_t DHT11_ReadBit(void) {
    int8_t bit = 0x00;
    // 1. 等待总线低电平结束
    while (!DHT11_READ);
    // 2. 延时后接收数据
    Delay_us(28);
    if (DHT11_READ) {
        bit = 1;
        // 3. 等待总线高电平结束
        while (DHT11_READ);
    } else {
        bit = 0;
    }
    return bit;
}

/**
 * @brief 读取一个字节的数据
 * @return 读取到的字节值
 */
int8_t DHT11_ReadByte(void) {
    int8_t byte = 0x00;
    for (uint8_t i = 0; i < 8; i++) {
        byte <<= 1;
        byte |= (DHT11_ReadBit() & 0x01);
    }
    return byte;
}

/**
 * @brief 获取温湿度数据
 * @param buffer: 存储数据的缓冲区
 * @return 1 表示成功,0 表示失败
 * @attention DHT11 自动释放总线,不用手动干预,且逻辑非的判断可能影响时序
 */
uint8_t DHT11_GetHumTemp(uint8_t *buffer) {
    // 发送起始信号并等待响应
    DHT11_Start();
    if (DHT11_Wait4Ack() == NACK) {
        return NACK; // 响应失败
    }
    // 读取 5 个字节的数据
    for (uint8_t i = 0; i < 5; i++) {
        buffer[i] = DHT11_ReadByte();
    }
    // 校验数据
    return (buffer[0] + buffer[1] + buffer[2] + buffer[3] == buffer[4]) ? 1 : 0;
}

4.2 主函数代码

/* @Descripttion: 串口打印 DHT11 测量的温湿度数据(基于寄存器实现) */
// DHT11 对时序要求比较严格,需要严格按照指定时序接收数据
// 时序模拟过程中尽可能减少无关指令
/* 引脚定义
DHT11: VCC ---> 3.3/5V
       DATA ---> PA5
       GND ---> GND
CH340: 5V ---> 5V
       GND ---> GND
       TX ---> PA10
       RX ---> PA9
*/
#include "stm32f10x.h"
#include "usart.h"
#include "dht11.h"

int main(void) {
    uint8_t DHT11_Data[5] = {0}; // 存储温湿度数据的缓冲区
    uint8_t readRes;             // 读取结果标志
    USART_Init();
    DHT11_Init();
    while (1) {
        // 读取温湿度数据
        readRes = DHT11_GetHumTemp(DHT11_Data);
        if (readRes) {
            // 数据读取成功,打印结果
            printf("Read Success!\r\n");
            printf("---------------------\r\n");
            printf("humidity: %d.%d %%RH \r\n", DHT11_Data[0], DHT11_Data[1]);
            printf("temperature: %d.%d C \r\n", DHT11_Data[2], DHT11_Data[3]);
            for (uint8_t i = 0; i < 5; i++) {
                printf("DHT11_Data[%d] = %d\n", i, *(DHT11_Data + i));
            }
            printf("CRC: 0x%02X \r\n", DHT11_Data[4]);
        } else {
            // 数据读取失败
            printf("Check Connected!\r\n");
        }
        printf("---------------------\r\n");
        // 每 3 秒读取一次
        Delay_ms(3000);
    }
}

4.3 测试效果

文章配图

参考资料

DHT11 奥松-ASAIR_PDF_数据手册 | 电容式温湿度传感器模块

目录

  1. 一、DHT11 概述
  2. 二、相关参数
  3. 2.1 电气特性
  4. 2.2 引脚说明
  5. 2.3 温湿度测试性能
  6. 三、通信方式(单线双向)
  7. 3.1 DHT11 简化单总线协议说明
  8. 3.2 DHT11 单总线数据格式
  9. 3.3 DHT11 通信时序说明
  10. 3.4 主从通信步骤
  11. 3.5 注意事项
  12. 四、参考代码 (基于 STM32)
  13. 4.1 DHT11 驱动代码
  14. 1、dht11.h
  15. 2、dht11.c
  16. 4.2 主函数代码
  17. 4.3 测试效果
  18. 参考资料
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • GitHub 项目本地运行指南:Python/Node.js/Java 实战部署与容器化
  • VRChat 翻译器 VRCT 使用指南与功能详解
  • Windows 系统 Visual C++ 运行库故障诊断与修复指南
  • 夸克网盘精选资源合集:书籍、软件、教程与素材
  • AMD 显卡运行 ComfyUI-Zluda 配置与优化指南
  • 从非科班无实习到入职大厂前端:开发之外的事才是破局关键
  • PetaLinux 设备树配置深度剖析与驱动集成
  • Arduino BLDC 基于串口指令的远程控制工业巡检机器人
  • 2025 AI 年度复盘:从 DeepSeek R1 开源到 Agent 商业化落地
  • Dify 接入企业微信群聊机器人详细步骤与部署实践
  • 季节 - 趋势分解(STL)方法详解
  • Mac Luminar Neo 深度体验:AI 驱动的高效修图方案
  • 绿联云 NAS 配置 WebDAV 实现公网访问与同步
  • 消息队列选型:Kafka、RabbitMQ 与 Redis 对比
  • 微信小程序原生开发入门:从零构建首个可交互页面
  • 汽车参数对比爬虫实战:从静态页面到动态渲染的Python技术栈解析
  • FPGA 结构与 CAD 设计核心概念解析
  • 数据中台血缘可视化实践:基于 Neo4j 的图数据库方案
  • 基于 Java 的家庭医生签约服务与健康管理平台
  • AI 应用开发技术深度解析:超越 API 调用的工程实践

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online