STM32 + DHT11 温湿度传感器详解
DHT11 是一款常用的数字式温湿度传感器,由电阻式感湿元件和 NTC 测温元件组成。它能够将环境中的温度和湿度转换为数字信号输出,具有成本低、使用方便等优点,广泛应用于智能家居、气象监测等领域。
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇
一、DHT11 温湿度传感器概述
DHT11 是一款常用的数字式温湿度传感器,由电阻式感湿元件和 NTC 测温元件组成。它能够将环境中的温度和湿度转换为数字信号输出,具有成本低、使用方便等优点,广泛应用于智能家居、气象监测等领域。
1. 主要特性
- 单总线通信:采用单总线协议与微控制器进行通信,仅需一根数据线即可完成数据传输。
- 测量范围:湿度测量范围为 20 - 90%RH,温度测量范围为 0 - 50°C。
- 精度:湿度测量精度为 ±5%RH,温度测量精度为 ±2°C。
- 数据输出:输出 40 位数据,其中包括 8 位湿度整数部分、8 位湿度小数部分、8 位温度整数部分、8 位温度小数部分和 8 位校验和。
2. 引脚说明
- VCC:电源引脚,接 3 - 5.5V 电源。
- DATA:数据引脚,用于与微控制器进行数据通信。
- GND:接地引脚。
二、STM32 与 DHT11 的硬件连接
将 DHT11 与 STM32 进行连接时,需要注意以下几点:
- 电源连接:将 DHT11 的 VCC 引脚连接到 STM32 的 3.3V 或 5V 电源引脚,GND 引脚连接到 STM32 的地引脚。
- 数据连接:将 DHT11 的 DATA 引脚连接到 STM32 的一个 GPIO 引脚,这里假设连接到 PA0 引脚。
- 上拉电阻:在 DATA 引脚和 VCC 引脚之间连接一个 4.7K - 10K 的上拉电阻,确保数据传输的稳定性。
三、DHT11 通信协议
DHT11 采用单总线通信协议,通信过程分为以下几个步骤:
1. 起始信号
STM32 向 DHT11 发送一个至少 18ms 的低电平信号,然后拉高 20 - 40μs,通知 DHT11 准备发送数据。
2. 响应信号
DHT11 接收到起始信号后,会拉低总线 80μs 作为响应信号,然后拉高 80μs 表示准备发送数据。
3. 数据传输
DHT11 依次发送 40 位数据,每位数据以 50μs 的低电平开始,高电平的持续时间决定了数据是 0 还是 1。如果高电平持续时间为 26 - 28μs,则表示数据 0;如果高电平持续时间为 70μs,则表示数据 1。
4. 校验和
最后 8 位为校验和,用于验证数据的准确性。校验和等于湿度整数部分、湿度小数部分、温度整数部分和温度小数部分的和的低 8 位。
四、STM32 代码实现
1. 初始化 GPIO 引脚
#include "stm32f10x.h"
// 初始化 PA0 引脚
void DHT11_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
2. 发送起始信号
// 发送起始信号
void DHT11_Start(void) {
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_ms(20); // 确保 DHT11 处于稳定状态
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
Delay_ms(20); // 至少 18ms 低电平
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_us(30); // 20 - 40μs 高电平
}
3. 等待响应信号
// 等待 DHT11 响应信号
uint8_t DHT11_Wait_Response(void) {
uint8_t retry = 0;
// 等待 DHT11 拉低总线
while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) && retry < 100) {
retry++;
Delay_us(1);
}
if (retry >= 100) return 1; // 响应超时
else retry = 0;
// 等待 DHT11 拉高总线
while (!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) && retry < 100) {
retry++;
Delay_us(1);
}
if (retry >= 100) return 1; // 响应超时
return 0;
}
4. 读取一位数据
// 读取一位数据
uint8_t DHT11_Read_Bit(void) {
uint8_t retry = 0;
// 等待低电平结束
while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) && retry < 100) {
retry++;
Delay_us(1);
}
retry = 0;
// 等待高电平
while (!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) && retry < 100) {
retry++;
Delay_us(1);
}
Delay_us(40); // 等待 40μs 判断数据位
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) return 1;
else return 0;
}
5. 读取一个字节数据
// 读取一个字节数据
uint8_t DHT11_Read_Byte(void) {
uint8_t i, dat = 0;
for (i = 0; i < 8; i++) {
dat <<= 1;
dat |= DHT11_Read_Bit();
}
return dat;
}
6. 读取温湿度数据
// 读取温湿度数据
uint8_t DHT11_Read_Data(uint8_t *humi_int, uint8_t *humi_dec, uint8_t *temp_int, uint8_t *temp_dec) {
uint8_t buf[5];
uint8_t i;
DHT11_Start();
if (DHT11_Wait_Response()) return 1; // 响应失败
for (i = 0; i < 5; i++) {
buf[i] = DHT11_Read_Byte();
}
// 校验和验证
if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) {
*humi_int = buf[0];
*humi_dec = buf[1];
*temp_int = buf[2];
*temp_dec = buf[3];
return 0; // 读取成功
} else {
return 1; // 校验和错误
}
}
7. 主函数
int main(void) {
uint8_t humi_int, humi_dec, temp_int, temp_dec;
DHT11_GPIO_Init();
while (1) {
if (!DHT11_Read_Data(&humi_int, &humi_dec, &temp_int, &temp_dec)) {
// 数据读取成功,可进行后续处理
// 例如通过串口打印数据
printf("Humidity: %d.%d%%, Temperature: %d.%d°C\n", humi_int, humi_dec, temp_int, temp_dec);
}
Delay_ms(2000); // 每 2 秒读取一次数据
}
}
注意事项
- 由于 DHT11 的数据传输对时序要求较高,因此在编写代码时需要确保延时函数的准确性。
- 为了避免干扰,建议在读取数据时关闭中断。
- DHT11 不适合频繁读取数据,建议读取间隔不小于 2 秒。
通过以上步骤,我们可以实现 STM32 与 DHT11 温湿度传感器的通信,获取环境的温度和湿度数据。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)