DHT11程序分析和测试

本篇文章对于DHT11进行测试,并且提供程序思路

先看一下DHT11的数据

 目前DHT11读出的湿度小数和温度小数都为0(和DHT11的版本有关),它采用单总线协议,但是和DS18B20的不同在于,它没有复杂的控制字节,以及设备编码,还有就是诸如eeprom和温度上下限等特殊存储功能,相比之下操作更简单一些。并且可以一次读出湿度和温度,比较方便。

 下面看一下具体时序操作

 首先主机要拉低总线至少18ms,并且主机可以马上拉高总线,等待DHT的响应信号,在响应信号后,它会有一段准备时间(DHT拉高总线),然后再拉低总线开始传送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1.格式见下面图示。

这个其实也比较好解决,可以在传送数据的时候等待高电平的到来,到来后等待60us(这个时间不是随意的,不能超过76-78,也就是50us+(26或28)),这个时候如果再去读取,电平为低的话,则为0,电平为高的话,则为1,然后再等待高电平过去。这个思想很好,可以好好想一下。下面提供程序思路

#include "DHT11.h"
void Delay19ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	_nop_();
	i = 1;
	j = 205;
	k = 97;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay60us()		//@11.0592MHz
{
	unsigned char i, j;

	i = 1;
	j = 162;
	do
	{
		while (--j);
	} while (--i);
}
//数据传输
uchar Read_Dat()
{
 uchar i; uchar Dat;
 for( i = 0 ; i < 8 ; i++ )
 {
  while( !DQ ); //等待低电平信号过去
  //延时60us并且去读取数据,如果是0的话,现在已经是越过了高电平并且50us的低电平已经过了约30us了
  //而如果是1,现在还是高电平。
  Delay60us();
  Dat <<= 1;
  if( DQ )
  {
   Dat |= 1;
  }
  //如果数据是0的话,就直接跳过了,去执行while( !DQ )来等待剩余的越20us低电平过去,并且进行下一次传送
  //如果数据是1的话,就等待高电平过去,然后执行while( !DQ )来等待50us的低电平过去,并且进行下一次传送
  while( DQ ); 
 }
 return( Dat );
 


}



/*响应信号是DHT11拉低总线    准备信号是DHT11拉高总线*/
uint Read_DHT11()
{
 uint Dat;
 uchar SD_z , SD_x , WD_z , WD_x , JY; //分别为湿度整数,湿度小数,温度整数,温度小数 , 校验值
 DQ = 1;
 _nop_();
 DQ = 0;          //拉低总线至少18ms
 Delay19ms();
 DQ = 1;          
 while( DQ );    // 主机拉高总线,并且等待DHT11响应信号
 while( !DQ );   //响应信号到来后,等待响应信号结束,(也即为等待准备信号 )
 while( DQ );    //准备信号到来后,等待准备信号结束,并开始数据传输
 SD_z = Read_Dat();
 SD_x = Read_Dat();
 WD_z = Read_Dat();
 WD_x = Read_Dat();
 JY = Read_Dat();
 //校验
  if( JY == ( SD_z + SD_x + WD_z + WD_x )  )
  Dat = ( ( uint )SD_z << 8 )| WD_z ;
  else
  Dat = 0;
 return( Dat );


}

这个程序其实是不好的,因为没有加超时退出,即如果条件没有达到,会卡死程序,一般调好了,不会出现这个问题,所以,要想更完美点,就加上超时退出就行了。

下面是串口收到的数据

发布了12 篇原创文章 · 获赞 67 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_37429313/article/details/87972648
今日推荐