主题 | 内容 | 教学目的/扩展视频 |
---|---|---|
DHT11芯片 | 电路连接,手册分析。驱动程序,读出数据。 | 能读出温湿度值即可。 |
师从洋桃电子,杜洋老师
📑文章目录
- 一、硬件接口与通信原理
- 1.1 硬件连接拓扑
- 1.2 单总线通信时序
- 二、驱动代码深度解析(dht11.c)
- 2.1 GPIO模式切换
- 2.2 起始信号生成
- 2.3 单bit数据读取
- 2.4 单字节数据读取
- 2.5 完整数据读取流程
- 三、关键优化策略
- 3.1 时序精度提升
- 3.2 错误重试机制
- 3.3 数据滤波处理
- 四、典型应用场景
- 五、开发注意事项
- 六、相关资源
▲ 回顾上期🔍DHT11数字温湿度传感器驱动开发全解析(上) | 零基础入门STM32第八十六步
▲ 回顾上期🔍DHT11数字温湿度传感器驱动开发全解析(中) | 零基础入门STM32第八十七步
一、硬件接口与通信原理
1.1 硬件连接拓扑
引脚 | 连接目标 | 说明 |
---|---|---|
VDD | 3.3V电源 | 供电范围3-5.5V DC |
DATA | PA15 | 单总线双向通信引脚 |
GND | 系统GND | 电源参考地 |
1.2 单总线通信时序
二、驱动代码深度解析(dht11.c)
2.1 GPIO模式切换
// 设置为推挽输出模式
void DHT11_IO_OUT(void) {GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = DHT11_IO;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 高速模式GPIO_Init(DHT11PORT, &GPIO_InitStruct);
}// 设置为上拉输入模式
void DHT11_IO_IN(void) {GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = DHT11_IO;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入GPIO_Init(DHT11PORT, &GPIO_InitStruct);
}
设计要点:
- 输出模式用于主机控制总线电平
- 输入模式配合上拉电阻保证总线稳定
- 50MHz速度满足单总线时序要求
2.2 起始信号生成
void DHT11_RST(void) {DHT11_IO_OUT(); // 切换输出模式GPIO_ResetBits(DHT11PORT, DHT11_IO); // 拉低总线delay_ms(20); // 保持低电平20ms(手册要求≥18ms)GPIO_SetBits(DHT11PORT, DHT11_IO); // 释放总线delay_us(30); // 等待20-40us
}
时序控制:
- 20ms低电平:确保满足最小18ms要求
- 30us高电平:预留足够响应时间
2.3 单bit数据读取
u8 Dht11_ReadBit(void) {u8 retry = 0;// 等待50us低电平起始信号while(GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO) && retry<100) {retry++;delay_us(1);}retry = 0;// 等待高电平到来while(!GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO) && retry<100) {retry++;delay_us(1);}delay_us(40); // 关键采样点return GPIO_ReadInputDataBit(DHT11PORT,DHT11_IO) ? 1 : 0;
}
解码原理:
- 26-28μs高电平:数据0
- 70μs高电平:数据1
- 40μs延迟采样:准确区分高低电平
2.4 单字节数据读取
u8 Dht11_ReadByte(void) {u8 i, dat = 0;for(i=0; i<8; i++) {dat <<= 1; // 高位先出dat |= Dht11_ReadBit();}return dat;
}
位操作逻辑:
- 左移操作保留高位
- 按位或操作累积数据位
- 循环8次组成完整字节
2.5 完整数据读取流程
u8 DHT11_ReadData(u8 *h) {u8 buf[5];DHT11_RST(); // 发送起始信号if(Dht11_Check() == 0) { // 检测传感器响应for(int i=0; i<5; i++) { // 读取5字节数据buf[i] = Dht11_ReadByte();}// 校验和验证if((buf[0]+buf[1]+buf[2]+buf[3]) == buf[4]) {h[0] = buf[0]; // 湿度整数部分h[1] = buf[2]; // 温度整数部分return 0; // 成功标志}}return 1; // 失败标志
}
数据格式解析:
字节 | 数据内容 | 数值范围 |
---|---|---|
0 | 湿度整数 | 20-90%RH |
1 | 湿度小数 | 固定为0 |
2 | 温度整数 | 0-50℃ |
3 | 温度小数 | 固定为0 |
4 | 校验和 | 前四字节和 |
三、关键优化策略
3.1 时序精度提升
// 使用硬件定时器替代delay_us
void Delay_us(uint16_t us) {TIM2->CNT = 0;while(TIM2->CNT < us);
}
3.2 错误重试机制
u8 DHT11_ReadData(u8 *h) {u8 retry = 3;while(retry--) {// ...读取逻辑...if(校验成功) return 0;delay_ms(100); // 重试间隔}return 1;
}
3.3 数据滤波处理
#define FILTER_SIZE 5
u8 filter_buf[FILTER_SIZE][2];void DHT11_Filter(u8 *h) {static u8 index = 0;// 存储当前值filter_buf[index][0] = h[0];filter_buf[index][1] = h[1];index = (index+1) % FILTER_SIZE;// 排序取中值// ...实现排序算法...
}
四、典型应用场景
五、开发注意事项
- 电源稳定性:建议并联100nF陶瓷电容
- 信号线长度:超过20米需增加屏蔽措施
- 采样间隔:严格≥1秒(手册要求)
- 环境适应:
- 避免冷凝环境
- 远离发热元件
- 防止化学污染
六、相关资源
[1] 洋桃电子B站课程-STM32入门100步
[2] STM32官方文档手册
[3] STM32F103固件函数库用户手册(中文)
[4] DHT11说明书(中文)
[5] DHT11温湿度显示程序
💬 技术讨论(请在评论区留言~)
📌 下期预告:下一期将探讨加速度传感器,欢迎持续关注!
点击查阅🔍往期【STM32专栏】文章
版权声明:本文采用[CC BY-NC-SA 4.0]协议,转载请注明来源
实测开发版:洋桃1号开发版(基于STM32F103C8T6)
更新日志:
- v1.0 初始版本(2025-03-30)