一、DHT11传感器概述

DHT11传感器概述

​ DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。 它应用专用的数字模块采集技术和温湿度传感技术, 确保产品具有极高的可靠性与卓越的长期稳定性。 ​ 传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接 。

image-20210527152514400
image-20210527152050788

DHT11传感器体积小,功耗极低,信号传输距离可达20米以上。具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。 产品为 4 针单排引脚封:

image-20210527152113012

DHT11与MCU连接图:

image-20210527152127031

二、DHT11通信协议分析

1. DHT11数据传输协议

​ DHT11通过DATA线与MCU实现半双工通讯。每次 通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明(当前小数部分用于以后扩展,现读出为零)。 操作流程如下:一次完整的数据传输为40bit,高位先出。 数据格式: ​ 40bits = 8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据 +8bit校验和

​ 数据传送正确时,校验和数据 “ 8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据” 所得结果的末8位。 ​ 即: ​ 校验和数据 =( 8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据)% 256。

2. DHT11数据通讯过程

​ (1)总线空闲状态为高电平,主机把总线拉低18毫秒,向DHT11发送开始信号。

​ (2)DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。

​ (3)主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。

​ (4) DHT11发送响应信号后,再把总线拉高80us,准备发送数据。

image-20210527152256797

(1)DHT11总共会发送40bits的数据,而每一bit数据都以50us低电平时隙开始。

​ (2)50us的低电平时隙结束后,接下来的高电平的长短决定了该数据位是0还是1。

​ (3)高电平时长在26~28us左右表示0,在70us左右表示1,格式见下面图示。

​ (4)如果读取响应信号一直为高电平,则表示DHT11没有响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。

image-20210527152323798

整个通讯过程如图所示:

image-20210527152342588

3.微秒级延时函数

#include “OnBoard.h”
	MicroWait(t)

三、实例演示

dht11.h

#ifndef __DHT11_H__
#define __DHT11_H__
#include "iocc2530.h"
extern unsigned char temperature,humidity;
extern int Start_DHT11(void);
#endif

dht11.c

#include "dht11.h"
#include "OnBoard.h"
#define DATA  P0_4

unsigned char temperature=0,humidity=0;
void DATA_IO_input_Cfg(void)//设置为上拉输入模式
{
    P0SEL &= 0xEF;   // 1110 1111 把P04设置为普通IO模式
    P0DIR &= 0xEF;   // 1110 1111 把P04设置为输入模式
    P0INP &= 0xEF;   // 1110 1111 把P04设置为上下拉模式
    P2INP &= 0xDF;   // 1101 1111 把P0组设置为上拉模式
}

void DATA_IO_output_Cfg(void)//设置为输出模式
{
    P0SEL &= 0xEF;   // 1110 1111 把P04设置为普通IO模式
    P0DIR |= 0x10;   // 0001 0000 把P04设置为输出模式
//    P0INP |= 0x10;   // 0001 0000 把P04设置为三态模式
}

unsigned char Read_Byte(void)
{
  unsigned char tmp=0,i;
  for(i=0;i<8;i++)
  {
    while(!(DATA ==0));//每个bit都是从50us的低电平开始
    while(!(DATA ==1));
    MicroWait(30);//延时30us
    if(DATA == 1)
    {
      tmp |= 1<<(7-i);//把该bit设置为1
    }
  }
  return tmp;
}

/*
@Start_DHT11 : 采集一次温湿度数据
@retval : 如果成功,把温湿度的值保存到全局变量,并返回1
          如果失败,返回0
*/
int Start_DHT11(void)//开始采集数据
{
  unsigned char buf[5];
  DATA_IO_output_Cfg();//设置为输出模式
  DATA = 0;//发送开始信号
  MicroWait(20000);//延时至少18ms
  DATA = 1;//拉高20~40us
  MicroWait(40);
  
  DATA_IO_input_Cfg();//设置为输入模式
  while(!(DATA ==0));//等DHT11回响应信号
  
  while(!(DATA ==1));//等DHT11把总线拉高,准备接收数据
  buf[0] = Read_Byte();
  buf[1] = Read_Byte();
  buf[2] = Read_Byte();
  buf[3] = Read_Byte();
  buf[4] = Read_Byte();

  
  if((buf[0]+buf[1]+buf[2]+buf[3])%256 == buf[4])
  {
    humidity = buf[0];
    temperature = buf[2];
    return 1;
  }
  return 0;
}