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

最近在总结做过的几个项目,今天小结一下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 out1\r\n");
		retry=0;
		return ;
	}else{
		retry = 0;
	}

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

while(((GPIOB->IDR & (1<<0))==0) && retry <100)//等待拉高
	{
		delay_us(1);
		retry++;
	}
	if(retry>= 100)
	{
		printf("time out2\r\n");
		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 out4\r\n");
			retry = 0;
			return ;
		}else{
			retry = 0;
		}
		
		delay_us(40);
		if((GPIOB->IDR & (1<<0))==0)
		{
			h1->humi_int &= ~(1<<(7-j));
		}else{
			h1->humi_int |= 1<<(7-j);
			while(((GPIOB->IDR & (1<<0))==1) && retry <100)//等待拉低
			{
				delay_us(1);
				retry++;
			}
			if(retry>= 100)
			{
				printf("time out5\r\n");
				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.%d\r\n",h1.humi_int,h1.humi_dec);
		printf("ture:%d.%d\r\n",h1.ture_int,h1.ture_dec);
	}	 

结果每次开发板复位后只有第一次能成功读取,之后每次读取都会在发出开始信号阶段就超时返回。一开始以为是时序的问题,但由于最开始可以成功读出一次数据,表明时序是可以正常工作的,之后根据数据手册的时序图又检查了一遍,发现没有写结束信号,时序图中的结束信号是由主机主动拉高的,因此我加上了主动拉高的代码,并延时500ms,但问题依旧没有解决,最后我重头到尾看了一遍数据手册发现了这个
在这里插入图片描述
发现了左下角的注:采样周期间隔不得低于1秒钟。
所以我在数据采样结束后主动拉高电平并延时1.5秒,成功解决问题!
——————————————————————————
CSDN下载要积分,DHT11的手册和驱动代码我放在公众号了:游侠嵌入式,需要的朋友请自取。(温湿度模块是我做植宠保姆的一个功能模块,其他还有ESP8266+boa服务器等,有时间我会把这些东西整理出来放在公众号,对本科毕业找工作还是有帮助的,卓越班的自己去取,也算是“传帮带”了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值