主题 | 内容 | 教学目的/扩展视频 |
---|---|---|
DHT11芯片 | 电路连接,手册分析。驱动程序,读出数据。 | 能读出温湿度值即可。 |
师从洋桃电子,杜洋老师
📑文章目录
▲ 回顾上期🔍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)