DHT11温湿度传感器

一.硬件介绍函数

RH是相对湿度,是用零点温度来定义的,通常,RH在45%~65%之间最为合适。spa

注:NTC为热敏电阻,输出为:单总线数字信号,单线双向串行通信。3d



注:上拉电阻状况下,配置为开漏输出,能够增长驱动能力,减少CPU功耗。blog







二.程序关键点:1)引脚输入与输出的准确切换,2)输出电平的准确延迟,3)输入电平的等待与延迟读取以及等待的时间限制。it

1.MCU如何设置开始信号?配置

/*
由MCU向DHT11发送一次开始信号,总线空闲状态为高电平,MCU把总线拉低至少18ms,
保证DHT11能检测到开始信号,主机发送开始信号后,能够切换到输入模式,或者切换到
高电平都可,切换到高电平时间一般为20~40us,而后开始读取响应信号.
*/
void DHT11_Rst(void)   
{                 
DHT11_IO_OUT(); //配置引脚为通用推挽输出模式
DAOBB = 0; //拉低DQ
    SysTickDelay(20000);//至少18ms
DAOBB = 1; 
SysTickDelay(30);//主机拉高20~40us
}
硬件

2.MCU如何接受响应信号?程序

/*
等待DHT11的回应
返回1:未检测到DHT11的存在
返回0:存在DHT11接受到主机的开始信号后,等待主机的开始信号结束,
而后发送80us的低电平响应信号,发送响应信号后,在把总线拉高80us,准备发送数据*/
u8 DHT11_Check(void)   
{   
u8 retry=0;
DHT11_IO_IN();//将A11口设为输入
  /*&&与<的优先级是<高于&&*/
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
{
retry++;
SysTickDelay(1);//这里系统滴答函数要配置为1US的中断

if(retry>=100)return 1;
else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
SysTickDelay(1);
}
if(retry>=100)return 1;   
return 0;
}
im

3.如何读取一个位的高低电平?前提是已经有响应信号,这样去读取数据才有意思。
一个位的高低电平是根据总线上的高电平的时间长度来判断的,说白了,就是低电平一旦结束,再过28us,总线上的电平为高,这个位的电平就是高电平,总线上的电平为低,这个位的电平就是低电平。因此咱们只要等待总线上的低电平结束,过了28us之后再70us以前去读总线上的电平,就能知道具体的一位的电平是多少了。但咱们不能无限制的等待低电平结束,假如器件故障或其余缘由,总线上始终低电平,这样程序就会在等待中死去,因此咱们必须加一个等待时间的限制,超过等待时间,咱们就放弃此次等待。为了使读取后总线上的高低电平不影响下一次的读取数据,咱们还加了一个高电平的限时等待。
数据

/*从DHT11读取一个位,返回值:1/0。
每一bit数据都以50us的低电平时序开始,高电平的宽度决定了bit数据位的0或1,
高电平状态在26~28us时,表示数据位为0,高电平状态在70us时,表示数据位为1.
DHT11_DQ_IN是读取对应端口引脚的输入电平,在读以前,该引脚要配置为上拉下拉输入模式
*/
u8 DHT11_Read_Bit(void)  
{
  u8 retry=0;
while(DHT11_DQ_IN&&retry<100)//读取高电平中,等待变为低电平,/*&&与<的优先级是<高于&&*/
{
retry++;
SysTickDelay(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//读取低电平中,等待变高电平
{
retry++;
SysTickDelay(1);
}
SysTickDelay(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;  
}

//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
for (i=0;i<8;i++) 
{
    dat<<=1; 
   dat|=DHT11_Read_Bit();
    }    
    return dat;
}

//从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi)     {          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]){*humi=buf[0];*temp=buf[2];}}else return 1;return 0;     }