《电子DIY》之基于STM32驱动温湿度传感器DHT11、DHT12

一,DHT11(12)传感器简介

DHT11 是一款湿温度一体化的数字传感器。该传感器包括一个电阻式测湿元件和一个 NTC 测温元件,通过单片机等微处理器简单的电路连接就能够实时的采集本地湿度和温度。DHT11 与单片机之间能采用简单的单总线进行通信,仅仅需要一个I/O 口。传感器内部湿度和温度数据 40Bit 的数据一次性传给单片机,数据采用校验和方式进行校验,有效的保证数据传输的准确性。DHT11 功耗很低,5V 电源电压下,工作平均最大电流 0.5mA。

湿度:
湿度,表示大气干燥程度的物理量。在一定的温度下在一定体积的空气里含有的水汽越少,则空气越干燥;水汽越多,则空气越潮湿。空气的干湿程度叫做“湿度”。在此意义下,常用绝对湿度、相对湿度、比较湿度、混合比、饱和差以及露点等物理量来表示;若表示在湿蒸汽中水蒸气的重量占蒸汽总重量(体积)的百分比,则称之为蒸汽的湿度。人体感觉舒适的湿度是:相对湿度低于70%(摘自百度)

工作特性:

 工作电压范围:3.5V-5.5V 
 工作电流 :平均 0.5mA 
 湿度测量范围:2090%RH 
 温度测量范围:050℃
 湿度分辨率 :1%RH 8 位
 温度分辨率 :18 位
 采样周期 :1S 
 单总线结构
 与 TTL 兼容(5V)

(摘自芯片手册)

二、引脚定义

在这里插入图片描述
在这里插入图片描述

三、典型连接电路

DHT11 数字湿温度传感器连接方法简单。第一脚接电源正,第四脚接电源地端。数据端为第二脚。可直接接主机(单片机)的 I/O 口。为提高稳定性,通常在数据端和电源正之间接一只 4.7K左右 的上拉电阻。第三脚为空脚,此管脚悬空不用。
在这里插入图片描述
在这里插入图片描述

四、DHT11内部数据结构

DHT11数字湿温度传感器采用单总线数据格式。即,单个数据引脚端口完成输入输出双向传输。其数据包由5Byte(40Bit)组成。数据分小数部分和整数部分。
一次完整的数据传输为40bit,高位先出

数据格式:

8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和
注:
1,校验和数据为前四个字节相加
2,传感器数据输出的是未编码的二进制数据,即数据(湿度、温度、整数、小数)之间应该分开处理

采集数据后的处理方式举例:
(设某时刻采集的数据如下:)

 byte4      byte3     byte2      byte1      byte0 
 00101101  00000010  00011100   00000001   01001001  (二进制)
 2DH		02H			1CH			01H		  49H    (十进制)
 45         2           28           1        76
 整数      小数       整数       小数       校验和
      湿度                 温度             校验和

由以上数据就可得到湿度和温度的值,计算方法:
humi (湿度)= byte4 . byte3=45.2 (%RH) 
temp (温度)= byte2 . byte1=28.1 () 
(校验和)= byte4+ byte3+ byte2+ byte1=76(=humi+temp)(校验正确) 
注意:DHT11一次通讯时间最大3ms,主机连续采样间隔建议不小于100ms。

五、DHT11采样时序

DHT11 开始发送数据流程:
在这里插入图片描述分析:
主机发送开始信号后,延时等待 20us-40us 后读取 DHT11 的应答信号,读取总线为低电平,说明 DHT11 发送响应信号,DHT11 发送响应信号后,再把总线拉高,准备发送数据,每一 bit 数据都以低电平开始,格式见如果读取响应信号为高电平,则 DHT11 没有响应,请检查线路是否连接正常。

主机复位信号和 DHT11 响应信号
在这里插入图片描述

数字‘0’信号表示方法

在这里插入图片描述
数字‘1’信号表示方法
在这里插入图片描述

六、DHT11程序源码

程序源码:
注:使用串口打印采集的温湿度数据(1秒采集一次数据)
DHT11 h文件

//Author: Liu Xianfei 0810
#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
typedef struct __DHT11_2
{
	u8 temperature[2];  //temperature
	u8 humidity[2];     //humidity
	u16 checksum;       //checksum
}DHT11;
extern DHT11 dht11;
#define DHT11PORT  GPIOA
#define DHT11PIN   GPIO_Pin_11
#define DHT11CLK  RCC_APB2Periph_GPIOA
//IO direction setting
#define DHT11_2_IO_IN()  {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<12;}
#define DHT11_2_IO_OUT() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<12;}
//IO operation function											   
#define	DHT11_2_DQ_OUT PAout(11) 
#define	DHT11_2_DQ_IN  PAin(11)  
//Function declaration
void DHT11_2_Init(void);
u8 DHT11_2_Read_Data(void);    
u8 DHT11_2_Read_Byte(void);
u8 DHT11_2_Read_Bit(void);
u8 DHT11_2_Check(void);
void DHT11_2_Rst(void); 
#endif

DHT11 C文件

#include "DHT11.h"

DHT11 dht11={0,0,0,0,0};

/*
*	Function name: initialize DHT11
*	Parameter: None
*	Return value: None
*	Author: Liu Xianfei 0810
*/
void DHT11_2_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(DHT11CLK,ENABLE);//Turn on the clock
	//Initialization pin
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=DHT11PIN;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(DHT11PORT,&GPIO_InitStruct);
 	GPIO_SetBits(DHT11PORT,DHT11PIN);//Pull up pin			    
}

/*
*	Function name: reset DHT11
*	Parameter: None
*	Return value: None
*/
void DHT11_2_Rst(void)	   
{                 
	DHT11_2_IO_OUT(); 	//SET OUTPUT
    DHT11_2_DQ_OUT=0; 	//pull downDQ
    delay_ms(20);    	//Pull down for at least 18ms
    DHT11_2_DQ_OUT=1; 	//DQ=1 
	delay_us(30);     	//Main engine pull-up 20 ~ 40us
}

/*
*	Function name: waiting for DHT11 to respond
*	Parameter: None
*	Return value: 1: DHT11 not detected 0: DHT11 detected
*/
u8 DHT11_2_Check(void) 	   
{   
	u8 retry=0;
	DHT11_2_IO_IN();//SET INPUT	 
    while (DHT11_2_DQ_IN&&retry<100)//DHT11 will pull down 40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)
		return 1;
	else 
		retry=0;
	//When DHT11 is pulled down, it will be pulled up again by 40-80us
    while (!DHT11_2_DQ_IN&&retry<100)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)
		return 1;	    
	return 0;
}

/*
*	Function name: read a bit from DHT11
*	Parameter: None
*	Return value: 1 or 0
*/
static u8 DHT11_2_Read_Bit(void) 			 
{
 	u8 retry=0;
	while(DHT11_2_DQ_IN&&retry<100)//Waiting for low level
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_2_DQ_IN&&retry<100)//Waiting for high level
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);
	if(DHT11_2_DQ_IN)
		return 1;
	else 
		return 0;		   
}

/*
*	Function name: read a byte from DHT11
*	Parameter: None
*	Return value: data of 1B
*	Author: Liu Xianfei 0810
*/
static u8 DHT11_2_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT11_2_Read_Bit();
    }						    
    return dat;
}

/*
*	Function name: read data once from DHT11
*	Parameter: temp: temperature value (range: 0 ~ 50 °) humi: humidity value (range: 20% ~ 90%)
*	Return value: 0, normal; 1, read failed
*/
u8 DHT11_2_Read_Data(void)    
{        
 	u8 buf[5];
	u8 i;
	DHT11_2_Rst();
	if(DHT11_2_Check()==0)
	{
		for(i=0;i<5;i++)//Read 40 bit data
		{
			buf[i]=DHT11_2_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			//Assignment
			dht11.humidity[0]=buf[0];
			dht11.humidity[1]=buf[1];
			dht11.temperature[0]=buf[2];
			dht11.temperature[1]=buf[3];
			dht11.checksum=buf[4];
		}
	}
	else 
		return 1;
	return 0;	    
}

延时函数 h文件

/*
	Filename: delay function
	Author: Liu Xianfei 0810
	Related note: use the system tick counter to realize the delay function
*/
#ifndef _delay_H
#define _delay_H 			   
#include "sys.h"   	 
void delay_init_liuxianfei0810(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif

延时函数 c文件

#include "delay.h"

static u8  fac_us=0;	//us delay multiplier
static u16 fac_ms=0;    //ms delay multiplier
	
/*
	Function name: initialization delay function
	Author: Liu Xianfei 0810
	Description:
		Systick clock is fixed to 1/8 of HCLK clock
		Sysclk: system clock
*/
void delay_init_liuxianfei0810(void)
{
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	
	//Select external clock HCLK/8
	fac_us=SystemCoreClock/8000000;							
	//1/8 of the system clock  
	fac_ms=(u16)fac_us*1000;		
	//Represents the number of systick clocks required per ms  
}								    

/*
	Function name: delay NUS function
	Author: Liu Xianfei 0810
	Description:
			nus is the number of us to delay						  MAXnus=2^24(LOAD)/fac_us
			=2^24(LOAD)/(SystemCoreClock/8000000)=2^24(LOAD)/9
*/    								   
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 					//Time loading	  		 
	SysTick->VAL=0x00;        					//Clear counter
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//Start countdown	  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		//Waiting time arrives  
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//Turn off counter
	SysTick->VAL =0X00;      					//Clear counter	 
}

/*
	Function name: delay NMS function
	Author: Liu Xianfei 0810
	Description: Delay nms
		Note the range of nms
		Systick -> load is a 24 bit register, so the maximum delay is:
				nms<=0xffffff*8*1000/SYSCLK
				Sysclk in Hz, nms in nms
				For 72MHz clock, nms <= 1864
*/
void delay_ms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;				
	//Time loading (systick ->LOAD is 24bit)
	SysTick->VAL =0x00;						
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	
	SysTick->VAL =0X00;       						    
} 

七、效果图

在这里插入图片描述

原创文章 59 获赞 52 访问量 1万+

猜你喜欢

转载自blog.csdn.net/liuxianfei0810/article/details/105886238