stm32 reads DHT11 temperature and humidity sensor

1. Preamble

We know that DHT11 is a single-bus protocol with only one data line.
And there is a pull-up circuit inside (below). Then the data line is high level by default, then we can explain how the host communicates with DHT11

figure 1

2. DHT11 response data format

Read the chip manual of DHT11, we can know that the data output of DHT11 is 40 bits at a time, and the high bit comes first.
Format: 8bit humidity integer data + 8bit humidity decimal data
+ 8bi temperature integer data + 8bit temperature decimal data + 8bit checksum
How is it checked?
If the data transmission is correct: checksum data = "8bit humidity integer data + 8bit humidity decimal data + 8bi temperature integer data + 8bit temperature decimal data" the last 8 bits
of the result . In this way, after we read the data of the temperature and humidity sensor, we can verify the data through the checksum. If it is correct, the data will be read, and if it is not correct, it will be re-read.

3. DHT11 communication process

Note: Here we use the time of high level on the bus to judge whether it is data '0' or data '1'.
Here we first give a general communication process
insert image description here

3.1 Generate start signal

The start signal is pulled from high to low, generating a falling edge. Keep the low level for more than 18ms,
and then release the bus (because the internal pull-up circuit, so after the release, the bus is high).
Wait for DHT11 to respond, if DHT11 responds, it will pull down the data line for 80us as a response signal.
Then release the bus. After a delay of 20-40us, the response data of DHT11 can be read.
insert image description here

3.2 Read data 0

DHT11 pulls the bus down for 50us, indicating that the data starts to be transmitted. DHT11 starts to send data information.
If it is data '0' the data line will be pulled high for 26-28us. This bit data transfer ends.
The next bit of data transmission starts, continue to pull it low for 50us to indicate the start of data transmission... until a complete data (40bit) transmission is completed.
insert image description here

3.3 Read data 1

DHT11 pulls the bus down for 50us, indicating that the data starts to be transmitted. DHT11 starts to send data information.
If it is data '1', it will pull the bus up for 70us. This bit data transfer ends.
insert image description here

DHT11 stop signal

Because a complete data is 40bi, when the last bit of data is transmitted, DHT11 pulls down the bus
for 50us, and then the bus is pulled up by the pull-up resistor to enter the idle state. (You can refer to the first communication general picture)

4. Code example

4.1 Read DHT11 source file

#include "DHT11.h"

GPIO_InitTypeDef GPIO_InitStructure;	//后面会改变输入输出状态

static void GPIO_SETOUT(void);
static void GPIO_SETIN(void);
static u8 DHT11_Check(void);

/**********************************************
函数名:static void DHT11_Rst(void)
参数说明:无
返回值:无
函数作用:主机发送开始信号
***********************************************/
static void DHT11_Rst(void)
{
    
                     
GPIO_SETOUT();											//配置成输出模式
GPIO_ResetBits(DHT11_IO,DHT11_PIN); //拉低数据线
delay_ms(20);    										//拉低至少18ms
GPIO_SetBits(DHT11_IO,DHT11_PIN); 	//拉高数据线 
delay_us(30);     									//主机拉高20~40us	
}


/**********************************************
函数名:u8 DHT11_Init(void)
参数说明:无
返回值:u8 ,返回1代表初始化成功,0则失败
函数作用:配置IO口,并发送开始信号
***********************************************/
u8 DHT11_Init(void){
    
    
	
//IO口配置	
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//换IO口需要修改
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出,如果需要考虑到IC的电流驱动能力时要接上拉电(5K)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(DHT11_IO,&GPIO_InitStructure);	
DHT11_Rst();//发送开始信号	
return DHT11_Check();//检测DHT11的响应
}


/**********************************************
函数名:static void GPIO_SETOUT(void)
参数说明:无
返回值:无
函数作用:配置IO口为推挽输出模式
***********************************************/
static void GPIO_SETOUT(void)
{
    
    
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出,如果需要考虑到IC的电流驱动能力时要接上拉电阻(5K)
GPIO_Init(DHT11_IO,&GPIO_InitStructure);
	
}

/**********************************************
函数名:static void GPIO_SETIN(void)
参数说明:无
返回值:无
函数作用:配置IO口为浮空输入模式
***********************************************/
static void GPIO_SETIN(void)
{
    
    
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入模式
GPIO_Init(DHT11_IO,&GPIO_InitStructure);
}


/**********************************************
函数名:static u8 DHT11_Check(void)
参数说明:无
返回值:检测到回应-->返回1,否则0
函数作用:检测DHT11的响应信号
***********************************************/
static u8 DHT11_Check(void) 	   
{
    
       
u8 retry=0;
GPIO_SETIN();			//设置为输入模式	
	
while (!GPIO_ReadInputDataBit(DHT11_IO,DHT11_PIN) && retry<100)//DHT11会拉低80us
 {
    
    
retry++;
delay_us(1);
 }
if(retry >= 100)	//超时未响应/未收到开始信号,退出检测
	return 0;
else 
	retry = 0;
while (GPIO_ReadInputDataBit(DHT11_IO,DHT11_PIN) && retry<100)//DHT11拉低后会再次拉高80us
 {
    
    
  retry++;
  delay_us(1);
 }
if(retry>=100)		//超时,DHT11工作出错,退出检测
	return 0;
	
	return 1;					//设备正常响应,可以正常工作
}


/**********************************************
函数名:static u8 DHT11_Read_Bit(void)
参数说明:无
返回值:返回从DHT11上读取的一个Bit数据
函数作用:从DHT11上读取一个Bit数据
***********************************************/
static u8 DHT11_Read_Bit(void)
{
    
    
u8 retry = 0;
//DHT11的Bit开始信号为50us低电平
while(GPIO_ReadInputDataBit(DHT11_IO,DHT11_PIN) && retry<100)//等待变为低电平(等待Bit开始信号)
{
    
    
 retry++;
 delay_us(1);
}
retry = 0;
while(!GPIO_ReadInputDataBit(DHT11_IO,DHT11_PIN) && retry<100)//等待变高电平(代表数据开始传输)
{
    
    
 retry++;
 delay_us(1);
}
delay_us(30);//等待30us
//0信号为26-28us,1信号则为70us,所以说超过30us去读取引脚状态就可以知道传输的值了
if(GPIO_ReadInputDataBit(DHT11_IO,DHT11_PIN)) return 1;
else return 0;		   
}


/***********************************************************************
函数名:static u8 DHT11_Read_Byte(void)
参数说明:无
返回值:返回从DHT11上读取的一个byte数据
函数作用:从DHT11上读取一个byte数据
************************************************************************/
static u8 DHT11_Read_Byte(void)    
{
    
            
u8 i,dat;
dat=0;	
for (i=0;i<8;i++) 
 {
    
    
   	dat<<=1; 
	dat|=DHT11_Read_Bit();
 }	
	
 return dat;
}


/**************************************************************************
函数名:u8 DHT11_Read_Data(u8 *temp,u8 *humi)
参数说明:temp:用于存放温度值(范围:0~50°),humi:用于存放湿度值(范围:20%~90%)
返回值:1:成功读取数据,0:读取数据出错
函数作用:从DHT11上读取温湿度数据(这里省略小数值)
***************************************************************************/
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{
    
            
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==1)	//设备响应正常
{
    
    
 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 0;		//设备未成功响应,返回0
	return 1;					//读取数据成功返回1
}

4.2 Read DHT11 header file

#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
#include "delay.h"


/* 设置GPIO脚,默认为PB1 */
#define DHT11_IO 		GPIOB
#define DHT11_PIN		GPIO_Pin_1

/* 初始化函数,如果DHT11存在响应则返回1,否则0 */
u8 DHT11_Init(void);                                                                                        
/* 从DHT11读取数据,没有小数部分 */
u8 DHT11_Read_Data(u8 *temp,u8 *humi);

#endif

5. Conclusion

5.1 Summarize the overall idea

Let me summarize first. Our idea is to understand the working principle of DHT11 through the chip manual of DHT11.
Including internal circuit, data response format, working timing, etc. Finally write code based on these.

5.2 Expectations of readers

I want to let readers know how to read the chip manual and how to analyze the working timing by explaining the example of reading DHT11. And how to write code, the last hope is that through this example, readers can draw inferences from one instance, and can analyze the working sequence and write code by themselves through the chip manual. This is very helpful to the improvement of personal ability. No matter what modules you encounter in the future, you can complete them independently.
Finally, thank you for reading!

Guess you like

Origin blog.csdn.net/qq_62553914/article/details/131161649
Recommended