资讯详情

【单片机】温湿度传感器 DHT11

文章目录

  • 前言
  • 模块介绍(可跳)
  • 模块使用
    • DHT11的参数说明
    • 数据包格式
    • DHT11传输时序
      • 发起通信
      • DHT11发送0和1时序
    • 代码:h文件
    • 代码使用方法
  • 代码获取

前言

大家好,我是林白柏;

希望看完能有所收获。请纠正不足!

PS:本文提到的所有模块都使用正点原子开发板战舰某宝现成的模块驱动模块。

PS:代码是正原子的代码,整理成自己习惯的界面


模块介绍(可跳过)

模块长这个亚子

image-20220423093916157

DHT11包装了8位MCU,单片机连接一个电阻感湿元件和一个NTC测温元件;

这8位数据的采集和处理都是由这8位数据处理的MCU当我们完成它时,我们只需要使用它MCU读数据;

传感器的外围电路也相对简单,只需要数据线DATA上拉。

模块使用

DHT11的参数说明

  • 湿度:20-90%RH;±5%RH
  • 温度:0-50℃;±2℃
  • 采样间隔:1s

数据包格式

DHT11采用,数据包格式如下:

是前四个字节的累加和,取低八位。

DHT11传输时序

发起通信

主机发送开始信号(降低)DATA线时间大于18ms),DHT11开始信号结束后发送响应信号(降低)DATA线80us),然后延时40-50us然后开始传输数据。 因此,主机发送开始信号后,会io设置为输入,延迟20-40us后检测DATA线电平状态可以知道DHT是否有响应。 对应代码如下 定义了几个宏,便于配置IO输入/输出、读写

#define DHT11_IO_IN() { 
          GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;} //IO配置为输入 #define DHT11_IO_OUT() { 
          GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;} //IO配置为输出 #define DHT11_DQ_OUT PGout(11) //写IO DHT11_DQ_OUT = 1;/DHT11_DQ_OUT = 0; #define DHT11_DQ_IN PGin(11) //读IO 

发送开始信号并延迟等待

static void DHT11_Rst(void) { 
                           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是否有响应信号

u8 dht11_check(void) 	   
{ 
           
	u8 retry=0;
	DHT11_IO_IN();//SET INPUT 
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us(响应信号)
	{ 
        
		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;}//超时,DHT11发送响应信号后,未把DATA线拉高
	return 0;
}

DHT11发送“0”和“1”的时序

发送“0”和“1”的区别只是高电平持续时间不一样。

“0”的时序 “1”的时序 对应代码如下

从DHT11读取1个bit,此处不判断每个bit开始阶段的低电平时间,(“0”传输时间接近40us,如果设置再长一点可能导致通讯失败);

static u8 DHT11_Read_Bit(void) 			 
{ 
        
 	u8 retry=0;
	while(DHT11_DQ_IN&&retry<100)//等待变为低电平
	{ 
        
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!DHT11_DQ_IN&&retry<100)//等待变高电平
	{ 
        
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if(DHT11_DQ_IN)return 1;
	else return 0;		   
}

知道1个bit怎么读取之后,就可以读取1个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;
}

知道1个byte读取过程,也就可以读取一帧完整的数据了(数据结构体部分看下文解释)

u8 dht11_read_data( dht11_data_t * data )  //data为用户传进来的结构体指针,用于返回读取的数据
{ 
                
 	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]) { 
        	//数据校验
		    memcpy( data, buf, sizeof( dht11_data_t ) );//校验通过,将数据传回给用户
            #if 0
                data->humi_int      = buf[0];
                data->humi_decimals = buf[1];
                data->temp_int      = buf[2];
                data->temp_decimals = buf[3];
            #endif
		}
	} 
    else { 
         
        return 1;
    }
    
	return 0; 
}

这个地方用结构体表示一帧数据(不包含校验和,因为用户不需要关心校验和,能传给用户的数据肯定是校验过的),因为使用了memcpy函数拷贝(该函数需要包含头文件string.h),dht11_data_t的数据存储格式需要跟buf匹配;

typedef struct { 
        
    uint8_t humi_int;
    uint8_t humi_decimals;
    uint8_t temp_int;
    uint8_t temp_decimals;
}dht11_data_t;

dht11_read_data中读取数据时,数据存到buf的格式如下

因为dht11_data_t成员变量都是uint8_t [1byte],所以为单字节对齐,跟buf是匹配的,可以直接用memcpy函数拷贝,存储格式如下

代码:h文件

头文件声明了两个函数:初始化函数,读取函数;DHT11采样间隔为1s,所以读取间隔需要大于1s,否则会读取失败;

uint8_t dht11_init(void);// 0:suc; 1:fail
uint8_t dht11_read_data( dht11_data_t * data );// 0:suc; 1:fail; 实测读取间隔需要大于1200ms

代码使用方法

读取前,需要先定义一个保存数据的结构体,然后把结构体的地址传进给dht11_read_data函数。

int main(void){ 
        
    dht11_data_t data;
    
    dht11_init();
    
    while(1) { 
        
        
        if( !dht11_read_data( &data ) ) { 
        
            _LOG_DEBUG( "[dht] humi %d.%d%%, temp %d.%dC\n\n", data.humi_int, data.humi_decimals
                                                             , data.temp_int, data.temp_decimals );
        }
        else { 
        
            _LOG_INFO("[err] dht read\n");
        }
        delay_ms(2000);
    }
}

代码获取

共用代码:https://gitee.com/sumoting1629/mcu-practice/tree/master/common

驱动代码:https://gitee.com/sumoting1629/mcu-practice/tree/master/component

标签: r3传感器参数易优控网络温湿度变送器ht7327集成电路

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台