👨💻个人主页:@开发者-削好皮的Pineapple!
👨💻 hello 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 削好皮的Pineapple! 原创
👨💻 收录于专栏:C语言到基于STM32 的智能矿探小车
文章目录
- ⭐前言⭐
- 🎶一、DHT11模块硬件连接
- 🎶二、DHT11模块工作原理及数据格式
- 1. 工作原理
- 2. 数据传输时序
- (1)整体时序
- (2)响应与数据准备阶段
- (3)数据位表示方法
- 3. 数据格式
- 🎶三、DHT11获取温湿度代码实现
- 1. 头文件(dht11.h)
- 2. 源文件(dht11.c)
- 结束语🥇
⭐前言⭐
在嵌入式开发中,温湿度检测是许多项目的基础功能,DHT11模块因其操作简便、成本较低等特点,常被用于温湿度数据的采集。本文将围绕基于STM32的DHT11模块温湿度检测展开介绍,帮助开发者了解相关硬件连接、工作原理、数据格式及代码实现。
🎶一、DHT11模块硬件连接
DHT11模块与开发板的连接较为简单,具体接线方式如下:
- vcc(+) --------- 3v3 / 5v:模块电源引脚,可连接开发板的3.3V或5V电源
- GND(-) --------- GND:模块接地引脚,连接开发板的GND
- DAT(out) ------- GPIO引脚上:模块数据输出引脚,开发板上自带的DHT11模块的DATA接在PG9上
通过以上连接,可实现DHT11模块与开发板之间的通信,为后续的数据采集做好硬件准备。有关更详细的硬件参数等信息,可参考手册《DHT11说明书最新版.pdf》。
🎶二、DHT11模块工作原理及数据格式
1. 工作原理
总线空闲状态为高电平,当主机需要获取温湿度数据时,会把总线拉低,且拉低时间必须大于18毫秒,以保证DHT11能检测到起始信号。
DHT11接收到主机的开始信号后,会等待主机开始信号结束,然后发送80us低电平响应信号。
主机发送开始信号结束后,延时等待20-40us,之后就可以读取DHT11的响应信号。主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,此时总线由上拉电阻拉高。
2. 数据传输时序
(1)整体时序
一次完整的数据传输包含起始信号、响应信号及数据传输阶段,时序图如下:
总线空闲状态为高电平,主机拉低总线>18ms发送起始信号;DHT11收到后,先发送80us低电平响应,再拉高80us准备发送数据。
(2)响应与数据准备阶段
- 总线为低电平时,说明DHT11发送响应信号;
- 响应后总线拉高80us,进入数据发送准备阶段;
- 每一bit数据以50us低电平时隙开始,高电平持续时间决定数据位是0还是1;
- 若读取响应信号为高电平,说明DHT11无响应,需检查线路;
- 最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
(3)数据位表示方法
-
数字0信号:低电平50us后,高电平持续26-28us,时序图如下:
-
数字1信号:低电平50us后,高电平持续70us,时序图如下:
3. 数据格式
一次完整的数据传输为40bit,高位先出,格式为:
8bit湿度整数数据 + 8bit湿度小数数据 + 8bit温度整数数据 + 8bit温度小数数据 + 8bit校验和
- 校验和 = 湿度整数 + 湿度小数 + 温度整数 + 温度小数
- 通过校验和可验证数据传输的正确性。
🎶三、DHT11获取温湿度代码实现
1. 头文件(dht11.h)
#ifndef __DHT11_H_
#define __DHT11_H_//dht11初始化接口
void dht11_init(void);extern unsigned char dht11_data[5];
void dht11_read_data(void);#endif
2. 源文件(dht11.c)
#include "stm32f4xx.h"
#include "dht11.h"
#include "delay.h"//DHT11的data引脚接在PG9上
#define DHT11_RCC RCC_AHB1Periph_GPIOG
#define DHT11_PORT GPIOG
#define DHT11_PIN GPIO_Pin_9 //GPIO引脚模式切换
//m=1:输出模式;m=0:输入模式
void gpio_mode_changed(int m)
{//使能时钟RCC_AHB1PeriphClockCmd(DHT11_RCC, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;if(m) //输出模式配置{GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_Pin = DHT11_PIN;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;}else //输入模式配置{GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;GPIO_InitStruct.GPIO_Pin = DHT11_PIN;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;}GPIO_Init(DHT11_PORT, &GPIO_InitStruct);
}//dht11初始化接口
void dht11_init(void)
{gpio_mode_changed(1) ; //初始化为输出模式GPIO_SetBits(DHT11_PORT, DHT11_PIN); //DATA引脚默认拉高
}//dht11发送起始信号
void dht11_start(void)
{gpio_mode_changed(1); //配置为输出模式GPIO_ResetBits(DHT11_PORT, DHT11_PIN); //拉低总线>18msdelay_ms(18);GPIO_SetBits(DHT11_PORT, DHT11_PIN); //释放总线delay_us(30); //等待20-40usgpio_mode_changed(0); //切换为输入模式//等待DHT11响应while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET);//等待响应结束while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == RESET);//等待数据发送开始while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET);
}//读取一个字节数据
unsigned char dht11_read_byte(void)
{gpio_mode_changed(0); //配置为输入模式unsigned char d = 0; //存储读取到的字节for(int i = 0; i < 8; i++){//等待50us低电平时隙结束while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == RESET);//延时35us:区分0和1(0的高电平≤28us,1的高电平≈70us)delay_us(35);//若仍为高电平,则为1if(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET){d |= (1 << (7 - i)); //高位先存}//等待当前bit的高电平结束while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET);}return d;
}//读取温湿度数据
unsigned char dht11_data[5] = {0}; //存储:湿度整+湿小小+温度整+温度小+校验和
void dht11_read_data(void)
{dht11_start(); //发送起始信号//读取40bit数据(5个字节)for(int i = 0; i < 5; i++){dht11_data[i] = dht11_read_byte();}
}
结束语🥇
🔥 订阅专栏持续学习:C语言到基于STM32的智能矿探小车
💬 欢迎点赞、收藏、留言讨论,一起攻克嵌入式开发!