×
单片机 > 单片机程序设计 > 详情

stm32驱动DHT11温湿度模块使用方法和问题小结

发布时间:2020-05-30 发布时间:
|

最近在总结做过的几个项目,今天小结一下DHT11模块的使用。

对DHT11的使用,就是编写时序和stm32进行通信。

DHT11和stm32是通过一根线进行通信的,双方通过这根线上的电平变化来识别各种信号。

DHT11每次传输数据会输出40bit的数据,即5个字节,它们的含义如下:

每一位bit是0还是1是通过高电平的持续时间来判断的,如下两张图所示,‘0’和

‘1’都是先持续50us的低电平,而后持续一段时间高电平,‘0’的高电平会持续26-28us,‘1’的电平会持续70us,因此你在判断每位数据是’0’还是’1’时,有两种方法,一种是看持续时间,显然高电平持续时间超过28us的就是’1’;另一种方法是选取一个时间点,比如在高电平开始40us后如果仍然是高电平,那就是‘1’,我用的第二种方式,因为即使是在40us后来检查电平,对数据是’0’的情况也很好判断,因为下一位数据’0’的持续时间是50us。

代码的话我贴几个比较重要的

stm32发出的开始信号,使引脚从高电平变为低电平,低电平持续20ms后再拉高电平,高电平持续40us等待DHT11发个响应信号,注意此时引脚应设为输入模式。


//主机拉低20ms

int retry=0;

set_out_high();

delay_ms(5);

set_out_low();

delay_ms(20);

set_in_high();

delay_us(40);


等待拉低代码如下,在编写时序时要检测到电平的变化可以使用下面的方法,使用while循环去检测,可以加上一个延时超时时间,我加的是100us,如果超过100us没有拉低就出错返回。


while(((GPIOB->IDR & (1<<0))==1) && retry <100)//等待拉低

{

delay_us(1);

retry++;

}

if(retry>= 100)

{

printf("time out1rn");

retry=0;

return ;

}else{

retry = 0;

}


等待拉高如下,功能同等待拉低相似


while(((GPIOB->IDR & (1<<0))==0) && retry <100)//等待拉高

{

delay_us(1);

retry++;

}

if(retry>= 100)

{

printf("time out2rn");

retry = 0;

return ;

}else{

retry = 0;

}


读取一个字节


for(j=0;j<8;j++)

{

while(((GPIOB->IDR & (1<<0))==0) && retry <100)//等待拉高

{

delay_us(1);

retry++;

}

if(retry>= 100)

{

printf("time out4rn");

retry = 0;

return ;

}else{

retry = 0;

}

delay_us(40);

if((GPIOB->IDR & (1<<0))==0)

{

h1->humi_int &= ~(1<

}else{

h1->humi_int |= 1<

while(((GPIOB->IDR & (1<<0))==1) && retry <100)//等待拉低

{

delay_us(1);

retry++;

}

if(retry>= 100)

{

printf("time out5rn");

retry = 0;

return ;

}else{

retry = 0;

}

}

}


判断’0’还是’1’的逻辑代码上面已经说了,可以结合代码看一看。

校验和的话,我没有使用,因为数据还是狠准确地。


在实际应用时遇到个问题,我是采用循环读的,如下


while(1)

{

    //清除之前的数据

h1.humi_dec=0;

h1.humi_int=0;

h1.ture_dec=0;

h1.ture_int=0;

//得到数据

humiture_get(&h1);

//打印数据

printf("humi:%d.%drn",h1.humi_int,h1.humi_dec);

printf("ture:%d.%drn",h1.ture_int,h1.ture_dec);

}  


结果每次开发板复位后只有第一次能成功读取,之后每次读取都会在发出开始信号阶段就超时返回。一开始以为是时序的问题,但由于最开始可以成功读出一次数据,表明时序是可以正常工作的,之后根据数据手册的时序图又检查了一遍,发现没有写结束信号,时序图中的结束信号是由主机主动拉高的,因此我加上了主动拉高的代码,并延时500ms,但问题依旧没有解决,最后我重头到尾看了一遍数据手册发现了这个

发现了左下角的注:采样周期间隔不得低于1秒钟。

所以我在数据采样结束后主动拉高电平并延时1.5秒,成功解决问题!



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
8051单片机的函数发生器的设计