DTH11测量温湿度学习(第十一天)

发布于:2025-07-23 ⋅ 阅读:(20) ⋅ 点赞:(0)

在这里插入图片描述


👨‍💻个人主页@开发者-削好皮的Pineapple!

👨‍💻 hello 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 削好皮的Pineapple! 原创

👨‍💻 收录于专栏C语言到基于STM32 的智能矿探小车


请添加图片描述

请添加图片描述


前言

在嵌入式开发中,温湿度检测是许多项目的基础功能,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); //拉低总线>18ms
	delay_ms(18);
	GPIO_SetBits(DHT11_PORT, DHT11_PIN); //释放总线
	delay_us(30); //等待20-40us
	gpio_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);
		//若仍为高电平,则为1
		if(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的智能矿探小车
💬 欢迎点赞、收藏、留言讨论,一起攻克嵌入式开发!


网站公告

今日签到

点亮在社区的每一天
去签到