一.硬件介绍

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

DHT11温湿度传感器_读取数据

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

DHT11温湿度传感器_i++_02

DHT11温湿度传感器_i++_03

DHT11温湿度传感器_读取数据_04

注:上拉电阻情况下,配置为开漏输出,可以增加驱动能力,减小CPU功耗。

DHT11温湿度传感器_输入模式_05

DHT11温湿度传感器_引脚_06

DHT11温湿度传感器_读取数据_07

DHT11温湿度传感器_数据_08

DHT11温湿度传感器_输入模式_09

DHT11温湿度传感器_引脚_10DHT11温湿度传感器_数据_11

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

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;

}

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;     

}


作者:柒月