问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

DHT11温湿度传感器原理与STM32单片机应用详解

创作时间:
作者:
@小白创作中心

DHT11温湿度传感器原理与STM32单片机应用详解

引用
CSDN
1.
https://m.blog.csdn.net/m0_51319492/article/details/141463359

DHT11是一款广泛应用于温湿度检测的数字传感器,它集成了温度和湿度测量功能,并通过单总线协议输出数字信号。本文将详细介绍DHT11的工作原理、硬件连接方式以及与STM32单片机的通信代码实现,帮助读者快速掌握这一常用传感器的使用方法。

一、DHT11介绍

DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,传感器内部包括一个8位单片机控制一个电阻式感湿元件和一个NTC测温元件。它采用类单总线协议传输数据,使用简单便捷。

测量温度范围在0-50℃,分辨率为1℃,误差在±2℃。湿度的测量范围位20%-95%RH,分辨率为1%RH,误差在±5%RH。工作电压为3.3V-5.5V。

二、DHT11原理图

下图为DHT11和单片机之间的接线图。DHT11的数据输出口接单片机的IO口,需要上拉一个5K左右的上拉电阻,保证空闲时刻处在高电平。

下图为DHT11电路原理图。DHT11一般都是内置上拉电阻的,不需要自行加装。

三、DHT11工作原理和时序

DHT11采用类单总线协议传输数据,与1-Wire协议存在异同之处。DHT11一次通信时间4ms左右,仪器上电后,要等待1s以越过不稳定状态,在此期间无需发送任何指令。

数据分为小数部分和整数部分,一次完整的数据传输为40bit,高位先出。数据格式为:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验。其中,8bit校验 = 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据,校验可以判断数据是否正确发送。

3.1 DHT11工作时序

主机发送起始信号以后,DHT11发送响应信号,然后发送40bit的数据,高位在前。下图为总时序图。

  • 起始信号:总线空闲状态由DHT11内置上拉电阻拉高,主机拉低总线至少18ms后释放总线20-40us。
  • DHT11响应:存在的DHT11会及时响应主机,同时拉低总线80us后,释放总线80us,然后拉低总线,表示开始传送数据。
  • 发送数据:当总线是低电平时表示开始发送数据,同时存在50us低电平时隙,之后拉高总线,高电平的持续时间表示发送0或者1,当高电平持续时间为26us-28us表示发送0,高电平持续时间为70us时,表示发送1。
  • 数据发送完毕,由上拉电阻拉高,置回空闲高电平状态。

四、DHT11代码

DHT11与STM32单片机连接使用时,需要将VCC接3.3V,GND接地,DAT接IO口,由于DHT11内置上拉电阻,可以将IO口配置成开漏输出模式,这样就不需要切换输入输出模式。如果配置成推挽输出模式,只能输出,不能输入,还需要在STM32接收数据时,配置成输入模式,比较麻烦。

下面为DHT11代码,其中包括时序部分,起始信号、DHT11响应、DHT11发送数据。DHT11_ReadData()函数中,需要校验STM32接收的数据是否正确。

/*
@brief:DHT11初始化
@param:无
@retval:无
*/
void DHT11_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	//开启GPIOA时钟
    GPIO_InitTypeDef GPIO_Initstructure;
    GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_OD;		//开漏输出
    GPIO_Initstructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_Initstructure);					//初始化GPIOPA7
    
    GPIO_SetBits(GPIOA,GPIO_Pin_7);							//默认高电平
}
/*
@brief:置PA7高低电平
@param:BitValue:1|0
@retval:无
*/
void WriteIO(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}
/*
@brief:DHT11起始信号
@param:无
@retval:无
*/
void DHT11_Start()
{
    WriteIO(0);		//主机拉低总线
    Delay_ms(20);	//至少拉低18ms
    WriteIO(1);		//释放总线
    Delay_us(30);	//释放总线20~40us
}
/*
@brief:起始信号以后检测DHT11的响应信号
@param:无
@retval:stateData,1表示DHT11响应,-1表示DHT11无响应
*/
uint8_t DHT11_Check()
{
    uint8_t stateData = 0;
    if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == RESET)//DHT11收到起始信号后会把总线拉低
    {
        Delay_us(80);//等待80us
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == SET)//DHT11拉高表示响应信号有用
        {
            stateData = 1;
        }
        else
        {
            stateData = 2;
        }
        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == SET);//引脚恢复低电平则表示传感器准备发数据
    }
    return stateData;
}
/*
@brief:接收DHT11传感器的一个字节数据
@param:无
@retval:Byte:接收的数据
*/
uint8_t DHT11_ReadByte()
{
    uint8_t i,Byte = 0x00;
    for(i=0;i<8;i++)
    {
        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == RESET);//DHT11每发一位数据之前,都先拉低,所以等待总线拉高
        Delay_us(40);//等待40us
        //高电平持续时间26-28us为0,70us为1
        if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7))
        {
            Byte |= (0x80>>i);//高位在前
        }
        while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7) == SET);//等待高电平结束,为下一次接收数据做准备
    }
    return Byte;
}
/*
@brief:接收DHT11传感器的温度和湿度
@param1:
@param1:
@retval:Byte:接收的数据
*/
uint8_t DHT11_ReadData(uint8_t *Hum,uint8_t *FHum,uint8_t *Temp,uint8_t *FTemp)
{
    uint8_t Buf[5];
    uint8_t i,Flag = 0;
    DHT11_Start();//起始信号
    if(DHT11_Check() == 1)//DHT11正确响应
    {
        for(i=0;i<5;i++)
        {
            Buf[i] = DHT11_ReadByte();//读取5个字节存在数组中
        }
        Delay_us(60);//保证完整读取
        if(Buf[0] + Buf[1] + Buf[2] + Buf[3] == Buf[4])//校验数据是否有效,如果有效
        {
            *Hum = Buf[0];		//湿度整数部分
            *FHum = Buf[1];		//湿度小数部分
            *Temp = Buf[2];		//温度整数部分
            *FTemp = Buf[3];	//温度小数部分
            Flag = 2;			//验证读取数据是否正确
            return Flag;
        }
        else//校验失败
        {
            *Hum = 0xFF;
            *FHum = 0xFF;
            *Temp = 0xFF;
            *FTemp = 0xFF;
        }
    }
    else//DHT11无响应
    {
        *Hum = 0xFF;
        *FHum = 0xFF;
        *Temp = 0xFF;
        *FTemp = 0xFF;
    }
}

主函数中调用函数,即可显示温湿度,湿度无小数位

DHT11_ReadData(&Hum_int,&Hum_dec,&Temp_int,&Temp_dec);	//读取DHT11的值,湿度整数,湿度小数,温度整数,湿度小数
OLED_ShowNum(40,25,Temp_int,2,OLED_8X16);			//温度整数部分
OLED_ShowChar(56,25,'.',OLED_8X16);
OLED_ShowNum(60,25,Temp_dec,1,OLED_8X16);			//温度小数部分
OLED_ShowNum(95,25,Hum_int,2,OLED_8X16);			//湿度整数部分
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号