时间记录:2024/1/29
一、DHT11引脚介绍
(1)VCC:电源引脚,3.3-5.5V
(2)DATA:数据输入输出引脚
(3)NC:保留引脚,悬空即可
(4)GND:电源地引脚
二、数据格式介绍
(1)一次完整的数据传输为40bit,高位先传
(2)40bit数据介绍:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验数据,前四byte数据值相加之和等于校验值
三、通讯过程
(1)空闲状态下,数据线处于高电平
(2)MCU拉低总线发出起始信号,保持至少18ms(18-30ms),然后释放总线,将总线拉高20-40us,然后DHT11便会发出响应(拉低总线80us,然后拉高总线80us),响应完毕后开始40bit数据的传输
(3)40bit数据介绍:DHT11拉低总线50us,然后拉高总线,高电平保持时间在26-28us表示数据“0”,保持时间在70us表示数据“1”
四、示例代码
(1)头文件
#ifndef __DHT11_H__
#define __DHT11_H__
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#define DHT11_OUT PAout(11)
#define DHT11_IN PAin(11)
//初始化
void vDHT11Init(void);
//获取温湿度
u8 xDHT11Get(u8* temp,u8* humi);
#endif
(2)源文件
#include "dht11.h"
static u8 Byte5Data[5];
//Program Size: Code=2028 RO-data=268 RW-data=40 ZI-data=1632
void vDHT11Init(void)
{
//1.使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//2.初始化GPIO
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_SetBits(GPIOA,GPIO_Pin_11);
Delay_Init();
Delay_Ms(1000);//DHT11上电启动时间
}
static void vLineOut(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
static void vLineIn(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
static void vStart(void)
{
vLineOut();
//启动过程
DHT11_OUT=0;//拉低至少18ms
Delay_Ms(20);
DHT11_OUT=1;//释放总线等待20-40us等待DHT11响应
Delay_Us(40);
vLineIn();
}
static u8 xGetOneByte(void)
{
u8 temp=0;
for(int i=0;i<8;i++){
while(!DHT11_IN);//等待50us拉低响应结束
temp <<= 1;
Delay_Us(40);//延时40us根据高电平时长判断0、1
if(DHT11_IN){
temp |= 0x01;
}
while(DHT11_IN);//等待高电平结束
}
return temp;
}
u8 xDHT11Get(u8* temp,u8* humi)
{
u8 crc=0;
vStart();
if(!DHT11_IN){
while(!DHT11_IN);//等待80us拉低响应结束
while(DHT11_IN);//等待80us拉高响应结束
//数据接收
for(int i=0;i<5;i++){
Byte5Data[i]=xGetOneByte();
}
*temp=Byte5Data[2];
*humi=Byte5Data[0];
//温度湿度相加计算校验和
for(int i=0;i<4;i++){
crc+=Byte5Data[i];
}
}
if(crc == Byte5Data[4])
return 0;
else
return 1;
}