DHT11温湿度传感器模块
DHT11温湿度传感器模块
·
一、传感器核心特性与技术解析
1. 传感器构成与工作原理
DHT11采用电容式感湿元件+NTC测温元件的复合传感方案,内部集成8位单片机处理模块。其工作流程分为三个阶段:
- 采样阶段:NTC热敏电阻通过惠斯通电桥测量温度,湿敏电容通过充放电特性检测湿度
- 模数转换:内置14位ADC将模拟信号转换为数字信号
- 数据封装:通过单总线协议将40位数据(湿度整数+湿度小数+温度整数+温度小数+校验和)传输至主机
1. 关键参数
| 项目 | 参数指标 | 技术说明 |
|---|---|---|
| 供电电压 | 3.3-5.5V | 支持宽压输入,兼容STM32/51等主流MCU |
| 测量范围 | 温度:0-50℃ / 湿度:20-90%RH | 极端环境需外接保护电路 |
| 精度 | 温度±2℃ / 湿度±5%RH | 长期使用需定期校准 |
| 采样周期 | ≥2s | 频繁读取会导致数据错误 |
二、工作原理与通信协议
1. 单总线通信时序
DHT11通过单根数据线实现双向通信,关键时序包括:
- 起始信号:主机拉低总线18-30ms后释放
- 响应信号:DHT11拉低总线83±5ms后拉高响应
- 数据传输:每bit以50μs低电平开始,高电平长度区分0/1(26-28μs为0,70μs为1)
原理图补充:
图一: 主机发送起始信号

图二:从机相应信号
2. 数据发送方式:
由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,位数据 “0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据“1”的格式为:54微秒的低 电平加68-74微秒的高电平。

3. 数据格式解析
40位数据结构:
8bit湿度整数 | 8bit湿度小数 | 8bit温度整数 | 8bit温度小数 | 8bit校验和
校验和=前4字节之和的末8位,需验证数据有效性
三、硬件连接示例
典型电路连接(以STM32为例):
DHT11引脚定义:
1: VCC 2: DATA 3: GND
- DATA引脚接STM32的GPIO(如PA6)
- 供电电压建议稳定在3.3-5.0V
四、代码实现(基于STM32 HAL库)
//DHT11.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "DHT11.h"
//配置DHT11为输出模式
void DHT11_Output_Mode(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PORT,&GPIO_InitStructure);
}
//配置DHT11为输入模式
void DHT11_Input_Mode(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO_PORT,&GPIO_InitStructure);
}
//输出电平0/1
void DHT11_DQ_OUT(uint8_t BitValue)
{
GPIO_WriteBit(DHT11_GPIO_PORT,DHT11_GPIO_PIN,(BitAction)BitValue);
}
//读取输入电平0/1
uint8_t DHT11_DQ_IN(void)
{
return GPIO_ReadInputDataBit(DHT11_GPIO_PORT,DHT11_GPIO_PIN);
}
//DHT11复位信号
void DHT11_Reset(void)
{
DHT11_Output_Mode();
DHT11_DQ_OUT(1);//拉高电平 保证待会是低电平
Delay_ms(25);//随便值
DHT11_DQ_OUT(0);//拉低DQ,复位信号的开始
Delay_ms(20);//拉低至少18ms
DHT11_DQ_OUT(1);// 将DHT11的DQ引脚拉高,结束复位信号
Delay_us(25); //在拉高DQ之后,DHT11会开始其内部复位过程,拉高20-40us
}
//检测是否有DHT11存在,0存在,1不存在
uint8_t DHT11_Check(void)
{
uint8_t retry = 0;//初始为0,用来重复计次
DHT11_Input_Mode();//设置PA9为输入模式,接收DHT11信号
// 等待DHT11拉低DQ引脚,这通常发生在复位信号之后的40-80微秒内
while(DHT11_DQ_IN() && retry < 100)//DHT拉低40-80us
{
retry++;//每次循环计次加一
Delay_us(1);
}
//如果在计次100次内没有被拉低,返回1则认为DHT11没有响应,否则重置计次变量为0,
//为下一次等待阶段做准备
if(retry >= 100) return 1;
else
{
retry = 0;
}
// 等待DHT11拉高DQ引脚,在拉低之后的40-80微秒内
// 如果DQ在100次重试内没有被拉高,同样认为DHT11没有正确响应
while(!DHT11_DQ_IN() && retry < 100)//DHT会再拉高40-80us
{
retry++;
Delay_us(1);
}
if(retry >= 100) return 1;
return 0;
}
//检测DHT11是否响应
uint8_t DHT11_Init(void)
{
DHT11_Output_Mode();
DHT11_Reset();
return DHT11_Check();
}
//读取一个位
uint8_t DHT11_Get_Bit(void)
{
uint8_t retry = 0;
while(DHT11_DQ_IN() && retry < 100)
{
retry++;
Delay_us(1);
}
retry = 0;
while(!DHT11_DQ_IN() && retry < 100)
{
retry++;
Delay_us(1);
}
Delay_us(40);
if(DHT11_DQ_IN()) return 1;
else return 0;
}
//读取一个字节
uint8_t DHT11_GetByte(void)
{
uint8_t i,Dat = 0;
for(i = 0; i < 8; i++)
{
Dat <<= 1;
Dat |= DHT11_Get_Bit();//Dat某一位或运算上1必定为1,或上0位不变
}
return Dat;
}
//指针temperature和humidity存储数据
uint8_t DHT11_GetData(uint8_t * temperature,uint8_t *humidity)
{
uint8_t H_H,H_L,T_H,T_L;
uint8_t HH,HL,TH,TL,CHECK;
uint8_t i;
DHT11_Reset();
if(DHT11_Check() == 0)
{
H_H = DHT11_GetByte();
H_L = DHT11_GetByte();
T_H = DHT11_GetByte();
T_L = DHT11_GetByte();
CHECK = DHT11_GetByte();
if((H_H+H_L+T_H+T_L)==CHECK)
{
*temperature = T_H;
*humidity = H_H;
}
}
else
{
return 1;//读取失败
}
return 0;//存在DHT11
}
//DHT11.h
#ifndef __DHT11_H__
#define __DHT11_H__
#define DHT11_GPIO_PORT GPIOA
#define DHT11_GPIO_PIN GPIO_Pin_6
uint8_t DHT11_Init(void);
void DHT11_Input_Mode(void);
void DHT11_Output_Mode(void);
void DHT11_DQ_OUT(uint8_t BitValue);
uint8_t DHT11_DQ_IN(void);
void DHT11_Reset(void);
uint8_t DHT11_Check(void);
uint8_t DHT11_Get_Bit(void);
uint8_t DHT11_GetByte(void);
uint8_t DHT11_GetData(uint8_t * temperature,uint8_t *humidity);
#endif
//main.c
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "DHT11.h"
uint8_t temperature,humidity;
int main()
{
OLED_Init();
while(DHT11_Init())//如果没有DHT11设备
{
OLED_ShowString(2,5,"NO DHT11");
Delay_ms(500);
OLED_ShowString(2,5," "); //刷新界面
}
while(1)//如果读取到数据
{
if(!DHT11_GetData(&temperature,&humidity))
{
OLED_ShowString(2,5,"temp:");
OLED_ShowString(3,5,"humi: %");
OLED_ShowNum(2,10,temperature,2);
OLED_ShowNum(3,10,humidity,2);
}
Delay_ms(1000);
}
}
五. 实验演示:
1.当没有连接DHT11模块时:

2.当正确连接DHT11模块时:

更多推荐

所有评论(0)