DHT11传感器的学习使用

相比于DS18B20只能测温度,DHT11能测温度之外还能测湿度,但是DHT11的精度和测量范围都要低于DS18B20

DHT11简介

  DHT11是一款价格便宜,易于使用的温度湿度测量二合一传感器。它具有超小体积、极低功耗的特点。它使用单总线与单片机进行双向的串行数据传输,信号传输距离可达20米以上,适用于对精度和实时性要求不高的温湿度测量场合。
在这里插入图片描述

DHT11封装与引脚说明

  DHT11一共有4个引脚,但是只用到3个,其中一个要悬空处理。
  DHT11使用单总线通信协议,使用时要将DATA线接电阻上拉,这个电阻一般取值5K左右。
在这里插入图片描述

DHT11工作原理

  一次完整的通信过程:单片机发送一次复位信号后,DHT11从低功耗模式转换到高速模式,等待主机复位结束后,DHT11拉低总线80us发送应答(ACK)信号,并拉高总线准备传输数据。拉高总线80us之后DHT11开始按照数据格式发送数据,当所有数据都发送完之后,DHT11 拉低总线 50us,表示数据传输完毕,随后总线由上拉电阻拉高进入空闲状态。

 数据格式

  DHT11一共5Byte数据,前2Byte为湿度的整数/小数数据,后1Byte为温度的整数/小数数据,最后1Byte为校验和,是前4Byte数据和的低八位,数据以 高位在前 方式传输。由于 DHT11的分辨率只能精确到个位,所以小数部分是数据全为0。
在这里插入图片描述

 工作时序

在这里插入图片描述

  • 首先单片机 拉低总线18ms以上,向DHT11发出起始信号,然后再 拉高总线20~40us 表示信号结束。
  • DHT11检测到起始信号后,拉低总线80us 发出应答信号,告诉主机数据已经准备好了,然后 DHT11 拉高总线80us,之后开始传输数据。
  • 每位数据的传输都由一次 50us的低电平 作为开始。与DS18B20不同,DHT11用 高电平的持续时间 表示数据是’0’还是’1’。高电平持续26~28us表示逻辑0,持续70us表示逻辑1
  • 最后1bit数据传输完毕之后,DHT11拉低总线50us表示传输结束,之后释放总线,由上拉电阻将总线上拉至高电平(空闲状态)

 注意事项

  1. DHT11上电后,要等待1秒以越过不稳定状态,在此期间不能发送任何指令。
  2. DHT11属于低速传感器,两次通信请求之间的间隔时间不能太短,一般不低于1秒。

 分辨0和1的方法

  由于 0 的高电平持续时间为 26-28us
     1 的高电平持续时间为 70us
  所以可以取高电平开始后 40us 的电平状态来确定数据是0还是1。如果是低电平,说明数据是0,因为0的高电平不能持续40us;如果是高电平,说明数据是1,因为1的高电平持续70us,此时高电平还未结束。
  40us而不是30us的原因是:信号不是精准的26~28us长度,有可能略大一些,也有可能略小一些,所以最好取得稍大一点。但是也不能取太长,否则会错过下一次开始信号。取40-50us都是不错的选择。


自己写的驱动程序(C51)

/**********************************************************************************
 * 程序名:    TM1638驱动程序
 * 作者:      DaveoCKII
 * 日期:      2020.3.4
 * 版本:      STC12C5A60S2 (延时函数时钟标准:11.0592MHZ)
 **********************************************************************************/

#ifndef _DHT11_H_
#define _DHT11_H_

#include <STC12C5A60S3.H>	// 自己修改过的STC12C5A60S2的头文件,为了区分原头文件改名S3
//------------------------------------定义列表------------------------------------//
sbit DATA = P3^2;           // 单总线口定义
unsigned char temp,humi;    // 温度,湿度
//------------------------------------函数列表------------------------------------//

unsigned char DHT11_Init(void);		// DHT11初始化函数
unsigned char DHT11_Read(void);		// DHT11读数据函数
unsigned char DHT11_Temp(void);		// DHT11读温度函数

void delay40us(void);       // 40us延时
void delay20ms(void);       // 20ms延时
void delay1us(void);        // 1us延时
void delay1s(void);         // 1s延时

//------------------------------------函数内容------------------------------------//

unsigned char DHT11_Init(void)
{
	unsigned char cnt=0;
	DATA=1;         // 总线初始化
	delay40us();
	DATA=0;         // 拉低总线20ms
	delay20ms();    
	DATA=1;
	delay40us();    // 等待DHT11响应
    
	while(!DATA){   // 检测低电平
		cnt++;
		delay1us();
	}
	if(cnt>100||cnt<40) {
		return 0;   // 初始化失败
	}
	cnt=0;
	while(DATA){    // 检测高电平
		cnt++; 
		delay1us();
	}
	if(cnt>100||cnt<40) {
		return 0;	// 初始化失败
	}
	
	return 1;	// 初始化成功
}

unsigned char DHT11_Read(void)
{
	unsigned char dat,i;
	for(i=0; i<8; i++)
	{
		while(DATA);    // 等待高电平结束 (数据信号)
		while(!DATA);   // 等待低电平结束 (起始信号)
		delay40us();    // 40us延时
		dat<<=1;     	// 数据格式:高位在前
		if(DATA)
			dat|=0x01;
	}
	return dat;
}

unsigned char DHT11_Temp(void)
{
	unsigned char succ;
	unsigned char buf[5];	// 数据暂存
    
	EA=0;               // 关中断防打扰
	succ=DHT11_Init();  // DHT11初始化
	if(!succ){          
		EA=1; 
		return 0;		// 初始化失败
	}
    
	for(succ=0; succ<5; succ++)		// 读取5Byte数据
		buf[succ]=DHT11_Read();
	
	if(buf[0]+buf[1]+buf[2]+buf[3]==buf[4]) {   // 验证结果
		humi = buf[0];		// 保存湿度值
		temp = buf[2];		// 保存温度值
		EA=1;
		return 1;	// 读取成功
	}
	else 
		EA=1;
	return 0;	// 读取失败
}

void delay40us(void) {
	unsigned char a,b;
	for(b=43;b>0;b--)
		for(a=1;a>0;a--);
}

void delay20ms(void) {
	unsigned char a,b,c;
	for(c=14;c>0;c--)
		for(b=168;b>0;b--)
			for(a=22;a>0;a--);
}

void delay1s(void) {
	unsigned char a,b,c;
	for(c=217;c>0;c--)
		for(b=171;b>0;b--)
			for(a=73;a>0;a--);
}

void delay1us(void) {  
	
}


//--------------------------------------------------------------------------------//


#endif


  DaveoCKII
2020.3.5

发布了5 篇原创文章 · 获赞 1 · 访问量 374

猜你喜欢

转载自blog.csdn.net/qq_39829913/article/details/104672452