文章目录
前言一、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();}//复位DHT11void DHT11_Rst(){DHT11_IO_OUT(); //SET OUTPUTDHT11_DQ_OUT=0; //拉低DQdelay_ms(20); //拉低至少18msDHT11_DQ_OUT=1; //DQ=1delay_us(30);//主机拉高20~40us}//等待DHT11的回应//返回1:未检测到DHT11的存在//返回0:存在u8 DHT11_Check(){u8 retry=0;DHT11_IO_IN();//SET INPUTwhile (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/0u8 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);//等待40usif(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版本驱动函数的编写