基于STM32的DHT11温湿度传感器设计

文章目录

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


前言

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

基于STM32的DHT11温湿度传感器设计_第1张图片


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

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

二、DHT11驱动程序详解

1.相关宏定义

基于STM32的DHT11温湿度传感器设计_第2张图片
由上可知DHT11温湿度传感器接入STM32,GPIOG,11引脚,如下图所示。基于STM32的DHT11温湿度传感器设计_第3张图片

2.输入输出GPIO配置

代码如下
基于STM32的DHT11温湿度传感器设计_第4张图片

2.GPIO初始化设计

总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高
基于STM32的DHT11温湿度传感器设计_第5张图片
代码如下
基于STM32的DHT11温湿度传感器设计_第6张图片

3.检测DHT11是否正常工作

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

基于STM32的DHT11温湿度传感器设计_第7张图片

4.读取DHT11数据

数据格式:

  • 8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
  • 读取数据将数据存入数组,这里仅保留了温度数据的整数位,注意数据较验方法,校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
    基于STM32的DHT11温湿度传感器设计_第8张图片

5.显示温湿度数据

数据处理函数
基于STM32的DHT11温湿度传感器设计_第9张图片
温湿度显示测试
基于STM32的DHT11温湿度传感器设计_第10张图片

三、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版本驱动函数的编写

你可能感兴趣的:(物联网传感器,STM32入门学习,stm32,单片机,arm)