STM32F103的DHT11(温湿度传感器模块)的配置和使用

先来认识一下这个传感器
DHT11温湿度传感器图片
在这里插入图片描述
以下是他的封装尺寸以及管脚介绍
1、VDD供电 3.3~5.5V DC
2、DATA 串行数据,单总线
3、NC 空脚
4、GND接地,电源负极
在这里插入图片描述

在这里插入图片描述
DHT11和单片机之间的通信时通过io口来通信的,以下是它的通信介绍

	DHT11 器件采用简化的单总线通信。单总线即只有一根数据线,系统中的数据交换、控制均由单总线完成。设备(主机或从机)通过一个漏枀开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线;单总线通常要求外接一个约 4.7kΩ 的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结极,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。
	单总线传送数据位定义DATA 用于微处理器与 DHT11 之间的通讯和同步,采用单总线数据格式,一次传送 40 位数据,高位先出。

上面一段话中所说的主机就是Stm32单片机,从机就是传感器内的一个8位单片机,传输模式是主机给从机发送一个信号,然后从机应答后返还给主机数据。主机和从机依靠一个IO口的高低电平进行通信。既然用到IO口那么我们就必须找到并配置这个IO口。

简单认识之后看开发板原理图DTH11是连接在哪个IO口
在这里插入图片描述
在这里插入图片描述
这个传感器连接在PG11 io口上,那么我们需要配置这个端口
之前配置io口,需要开启GPIOx的时钟,创建一个GPIO_initTypeDef结构体,选择管脚、输出速率、IO口输入输出模式,最后调用函数初始化IO在这里插入图片描述
PG11在GPIOG上,那初始化GPIO函数的第一个参数选择GPIOG,管脚和速率我们选择GPIO_Pin_11、GPIO_Speed_50MHz,只剩下IO口输入输出模式这个参数通过DTH11数据手册的时序图介绍可知
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述时序图有实线和虚线、实线代表主机信号(单片机信号)、虚线代表从机信号(DTH11响应的信号).
(1)主机通过拉低IO口之后至少延迟18ms,然后拉高IO口与从机通信,这个过程我们站在32芯片单片机的角度来看,io口当然要配置成输出模式。(2)那么从机响应信号后给主机返回信号,信号到达主机,主机通过读取IO口高低电平状态来读取数据,这个过程当然IO口要配置成输入模式。
这里主机既要求IO口配置成输出模式,从机又要求IO口配置成输入模式,我们怎么解决这个矛盾?
在这里插入图片描述
查询GPIO口输出模式得到将IO口配置成开漏模式可以解决这个矛盾,至此配置IO口的所有参数确定
dht11.h头文件代码:

#ifndef __DHT11_H
#define __DHT11_H

#include "stm32f10x.h"
#define dht11_High() GPIO_SetBits(GPIOG,GPIO_Pin_11)
#define dht11_low()  GPIO_ResetBits(GPIOG,GPIO_Pin_11)
#define dht11_readG11()  GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_11)
struct dht11_data
{
		int8_t tem;
		uint8_t humidity;
};
extern struct dht11_data sj;
extern uint8_t shuju[5];
void dht11_config(void);
uint8_t dht11_readdata(void);

#endif

DTH11配置函数:

void dht11_config(void)
{
		//初始化io口
	//开启APB2时钟树上的GPIOG的时钟
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
	//配置PG11管脚的输出模式为开漏输出,输出速率为50MHz
		GPIO_InitTypeDef inittypedef={0};
		inittypedef.GPIO_Pin=GPIO_Pin_11;
		inittypedef.GPIO_Speed=GPIO_Speed_50MHz;
		inittypedef.GPIO_Mode=GPIO_Mode_Out_OD;
		//初始化GPIO函数
		GPIO_Init(GPIOG,&inittypedef);
		//将PG11管脚设为高电平
		dht11_High();
}

配置完之后就需要考虑获取数据的流程了
首先了解需要获取的数据格式

DHT11传输的数据格式:

8bit 湿度整数数据 + 8bit 湿度小数数据 + 8bit 温度整数数据 + 8bit 温度小数数据 + 8bit 校验位。

可以看到他传输的数据有温度、湿度、一字节的校验位。那么校验位的依据是什么?来看一个例子在这里插入图片描述
在这里插入图片描述

我们可以通过数据传输的时序图来编程,以下是时序图在这里插入图片描述
传输数据步骤:
/------------------------第一个信号----------------------------/
我们当前是站在主机角度编程,那么第一个时序应该拉低总线、延迟18ms、拉高总线。这样从机就会感应到这个信号
/------------------------第二个信号----------------------------/
之后的信号都是主机感应从机输入到IO口的高低电平
第二个信号等待一个低电平,如果等待时间内低电平未到达就传输错误。
再等待一个高电平,如果等待时间内低电平未到达就传输错误。之后开始接受数据
/-----------------------接收数据信号-------------------------/
开始接受数据“0”和“1”,这里的0和1数据是这样的在这里插入图片描述0数据:
*****先等待一个将总线拉低54us的信号,然后等待一个将总线拉高23us~27us的信号
1数据:
*****先等待一个将总线拉低54us的信号,然后等待一个将总线拉高68us~74us的信号
那么如何判断信号是0或1呢?我们可以先等待总线拉低然后利用延时函数延时54us,然后延时30us,此时读取总线的状态,如果是高电平那么就是数据“1”,否则为“0”.
最后加上结束信号
上代码

uint8_t dht11_readdata(void)
{
		uint8_t waittime=0;
		//第一个信号
		dht11_High();
		dht11_low();
		Delay_ms(20);
		dht11_High();
		//第二个信号
		while(dht11_readG11()==1)//等待一个低信号
		{
				Delay_us(1);
				waittime++;
				if(waittime>=100)
				{
					return 1;
				}
		}
		waittime=0;
		while(dht11_readG11()==0)//等待一个高信号
		{
				Delay_us(1);
				waittime++;
				if(waittime>=100)
				{
					return 1;
				}
		}
		//开始读取数据
		for(int i=0;i<40;i++)
		{
			waittime=0;
			//等待一个低信号
				while(dht11_readG11()==1)
				{
					Delay_us(1);
					waittime++;
					if(waittime>=100)
					{
						return 1;
					}
				}
				waittime=0;
			//等待一个高信号
				while(dht11_readG11()==0)
				{
					Delay_us(1);
					waittime++;
					if(waittime>=100)
					{
						return 1;
					}
				}
				Delay_us(30);
				if(dht11_readG11()==0)
				{
							//数据为0
						shuju[i/8]&=1<<(7-i%8);
				}else{
						//数据为1
					shuju[i/8]|=~(1<<(7-i%8));
				}
		}
		//结束信号
		Delay_us(54);
		dht11_High();
		//验证数据是否正确
		if(shuju[0]+shuju[1]+shuju[2]+shuju[3]==shuju[4])
		{
				//数据正确
			sj.humidity=shuju[0];
			sj.tem=shuju[2];
			if((shuju[3]&1<<7)!=0)//如果温度最高位为1,是负数
			{
					sj.tem=-shuju[2];
			}
			return 0;
		}
		else{
				printf("数据校验失败\r\n");
		}
		return 2;
}
  • 32
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值