STM32实现DHT11温湿度传感器设计

文章目录

  • 前言
  • 一、DHT11温湿度传感器是什么?
  • 二、DHT11驱动程序详解
  • 1.相关宏定义
  • 2.输入输出GPIO配置
  • 2.GPIO初始化设计
  • 3.检测DHT11是否正常工作
  • 4.读取DHT11数据
  • 5.显示温湿度数据
  • 三、DHT11驱动源码
  • 总结

  • 前言

    DHT11作为一款低价、入门级的温湿度传感器,常用于我们的单片机设计实例中;它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
    DHT11为 4 针单排引脚封装,如下图,采用单线制串行接口,只需加适当的上拉电阻,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选择。


    一、DHT11温湿度传感器是什么?

    详见:物联网外设学习笔记-数字温湿度传感器

    二、DHT11驱动程序详解

    1.相关宏定义


    由上可知DHT11温湿度传感器接入STM32,GPIOG,11引脚,如下图所示。

    2.输入输出GPIO配置

    代码如下

    2.GPIO初始化设计

    总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高

    代码如下

    3.检测DHT11是否正常工作

    检查DHT11是否正常,正常的话会在单片机发送起始信号完成后,传感器返回80us低电平,然后发送80us高电平。即证明DHT11工作正常,该函数工作正常返回0,否则返回1,该函数中利用了while循环检测在一定时间内的电平变化,此类用法在后面也会经常用到。

    4.读取DHT11数据

    数据格式:

  • 8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
  • 读取数据将数据存入数组,这里仅保留了温度数据的整数位,注意数据较验方法,校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
  • 5.显示温湿度数据

    数据处理函数

    温湿度显示测试

    三、DHT11驱动源码

    头文件

    #ifndef _dht11_H
    #define _dht11_H
    
    #include "system.h"
    #include "SysTick.h"
    
    
    #define DHT11 (GPIO_Pin_11) //PG11
    #define GPIO_DHT11 GPIOG
    
    #define DHT11_DQ_IN PGin(11)	  //输入
    #define DHT11_DQ_OUT PGout(11)  //输出
    
    void DHT11_IO_OUT(void);
    void DHT11_IO_IN(void);
    u8 DHT11_Init(void);
    void DHT11_Rst(void);
    u8 DHT11_Check(void);
    u8 DHT11_Read_Bit(void);
    u8 DHT11_Read_Byte(void);
    u8 DHT11_Read_Data(u8 *temp,u8 *humi);
    
    
    #endif
    
    

    源文件

    #include "dht11.h"
    
    
    //DHT11初始化
    //返回0:初始化成功,1:失败
    u8 DHT11_Init()
    {
        GPIO_InitTypeDef GPIO_InitStructure;
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
    
        GPIO_InitStructure.GPIO_Pin=DHT11;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);
    	
        GPIO_SetBits(GPIO_DHT11,DHT11);	   //拉高
    
        DHT11_Rst();
        return DHT11_Check();
    }
    
    //复位DHT11
    void DHT11_Rst()
    {
        DHT11_IO_OUT(); 	//SET OUTPUT
        DHT11_DQ_OUT=0; 	//拉低DQ
        delay_ms(20);    	//拉低至少18ms
        DHT11_DQ_OUT=1; 	//DQ=1
        delay_us(30);     	//主机拉高20~40us
    }
    
    //等待DHT11的回应
    //返回1:未检测到DHT11的存在
    //返回0:存在
    u8 DHT11_Check()
    {
        u8 retry=0;
        DHT11_IO_IN();//SET INPUT
        while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~50us
        {
            retry++;
            delay_us(1);
        };
        if(retry>=100)return 1;
        else retry=0;
        while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~50us
        {
            retry++;
            delay_us(1);
        };
        if(retry>=100)return 1;
        return 0;
    }
    
    //从DHT11读取一个位
    //返回值:1/0
    u8 DHT11_Read_Bit(void)
    {
        u8 retry=0;
        while(DHT11_DQ_IN&&retry<100)//等待变为低电平 12-14us 开始
        {
            retry++;
            delay_us(1);
        }
        retry=0;
        while(!DHT11_DQ_IN&&retry<100)//等待变高电平	 26-28us表示0,116-118us表示1
        {
            retry++;
            delay_us(1);
        }
        delay_us(40);//等待40us
        if(DHT11_DQ_IN)return 1;
        else return 0;
    }
    
    //从DHT11读取一个字节
    //返回值:读到的数据
    u8 DHT11_Read_Byte(void)
    {
        u8 i,dat;
        dat=0;
        for (i=0; i<8; i++)
        {
            dat<<=1;
            dat|=DHT11_Read_Bit();
        }
        return dat;
    }
    
    //从DHT11读取一次数据
    //temp:温度值(范围:0~50°)
    //humi:湿度值(范围:20%~90%)
    //返回值:0,正常;1,读取失败
    u8 DHT11_Read_Data(u8 *temp,u8 *humi)
    {
        u8 buf[5];
        u8 i;
        DHT11_Rst();
        if(DHT11_Check()==0)
        {
            for(i=0; i<5; i++) //读取40位数据
            {
                buf[i]=DHT11_Read_Byte();
            }
            if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
            {
                *humi=buf[0];
                *temp=buf[2];
            }
    
        } else return 1;
        return 0;
    }
    
    //DHT11输出模式配置
    void DHT11_IO_OUT()
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin=DHT11;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	 //推挽输出
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);
    }
    
    //DHT11输入模式配置
    void DHT11_IO_IN()
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin=DHT11;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;	 //上拉输入模式
        GPIO_Init(GPIO_DHT11,&GPIO_InitStructure);
    }
    
    

    测试函数

    #include "system.h"
    #include "SysTick.h"
    #include "led.h"
    #include "usart.h"
    #include "tftlcd.h"
    #include "dht11.h"
    
    
    void data_pros()	//数据处理函数
    {
    	u8 temp;  	    
    	u8 humi;
    	u8 temp_buf[3],humi_buf[3];
    	DHT11_Read_Data(&temp,&humi);
    	temp_buf[0]=temp/10+0x30;	
    	temp_buf[1]=temp%10+0x30;
    	temp_buf[2]='\0';
    	LCD_ShowString(80,100,tftlcd_data.width,tftlcd_data.height,16,temp_buf);
    		
    	humi_buf[0]=humi/10+0x30;	
    	humi_buf[1]=humi%10+0x30;
    	humi_buf[2]='\0';
    	LCD_ShowString(80,130,tftlcd_data.width,tftlcd_data.height,16,humi_buf);		
    }
    
    int main()
    {
    	u8 i=0;
    	SysTick_Init(72);
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组
    	LED_Init();
    //	USART1_Init(9600);
    	TFTLCD_Init();			//LCD初始化
    	
    	LCD_Printf("Temp:   C",10,100,24,2,WHITE,BLACK);
    	LCD_Printf("Humi:   %RH",10,130,24,2,WHITE,BLACK);	
    	while(DHT11_Init())	//检测DHT11是否纯在
    	{
    		LCD_Printf("DHT11 Init Error",30,50,24,2,WHITE,BLACK);
    		delay_ms(500);		
    	}
    	LCD_Printf("DHT11 Init Success",30,50,24,2,WHITE,BLACK);
    	
    	while(1)
    	{
    		
    		i++;
    		if(i%20==0)
    		{
    			led1=!led1;
    			data_pros();  	 //读取一次DHT11数据最少要大于100ms
    		}
    		delay_ms(10);
    			
    	}
    }
    
    

    总结

    以上就是今天要讲的内容,本文仅仅简单介绍了DHT11温湿度传感器,及STM32版本驱动函数的编写

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32实现DHT11温湿度传感器设计

    发表评论