DHT11(温湿度模块)

 1.引脚介绍

从左到右引脚依次为:

2.接线

1.单总线通常要求外接一个约 4.7kΩ 的上拉电阻,这样,当总线闲置时,其状态为高电平。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问器件都必须严格遵循单总线序列,如果出现序列混乱,器件将不响应主机。(在第3章节.通信协议里讲)

2.从图中还可以看出要共地
 

3.通信协议

         dht11采用单总线通信,是非常简单的主从通信模式。

        由于只有一条数据线,并且还是双向的,所以说必须规定谁先发数据,主机应该发什么样子的波形(应该是先拉低一段时间,因为平时是高电平),然后从机看到是双方规定好的波形,该我发数据了,把温湿度以规定好的波形发给主机,主机看懂后就知道温湿度多少了。

        具体主机发什么波形,从机发什么呢,先大概看一下波形:

        可以看出并不是高电平为1,低电平为0,而是根据拉高的时间,从波形上看1比0宽一点,这是我们区分数据的关键

        主机先拉低(起始信号)拉高(释放总线),从机也拉低(响应)拉高(响应),之后发送40位数据(可以转化为实际的温湿度),最后还有一个拉低(dht11结束信号)

具体时间内对应下表:

4.代码

#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"
//DATA引脚	GPIOG,GPIO_Pin_11	注意:只用修改下方
#define dht11GPIOX	GPIOB
#define dht11GPIO_Pin_X	GPIO_Pin_6
#define	RCC_APB2Periph_GPIO	RCC_APB2Periph_GPIOB
typedef struct{
	uint8_t Tem;
	uint8_t Hum;
}DHT11_DATA;
extern DHT11_DATA dht11;
void DHT11_Config(void);
uint8_t DHT11_ReadData(void);//获取温湿度数据到结构体dht11里,成功返回0,超时返回1,数据校验失败返回2
#endif

#include "dht11.h"
#include "delay.h"

DHT11_DATA dht11={0};
#define DHT11_High()  GPIO_SetBits(dht11GPIOX,dht11GPIO_Pin_X)
#define DHT11_Low()  	GPIO_ResetBits(dht11GPIOX,dht11GPIO_Pin_X)
#define DHT11_Read()	GPIO_ReadInputDataBit(dht11GPIOX,dht11GPIO_Pin_X)

void DHT11_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct={0};
	//1,开时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO,ENABLE);
	//2,配置GPIO
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//开漏模式
	GPIO_InitStruct.GPIO_Pin = dht11GPIO_Pin_X;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(dht11GPIOX,&GPIO_InitStruct);
	//3,默认拉高
	DHT11_High();
}

//读取DHT11数据
uint8_t DHT11_ReadData(void)
{
	uint16_t cnt=0,i=0;
	uint8_t data[5]={0};//前8位,保存在data[0]
	//1,起始信号
	DHT11_High();
	DHT11_Low();
	Delay_ms(20);
	DHT11_High();
	//2,等待从机响应信号
	while(DHT11_Read() == 1) //等待低电平到来
	{
		cnt++;
		Delay_us(1);
		if(cnt>100) 
		return 1;//通信超时	
	}
	cnt=0;//下次使用之前先清零
	while(DHT11_Read() == 0) //等待高电平到来
	{
		cnt++;
		Delay_us(1);
		if(cnt>100) 
		return 1;//通信超时	
	}
	//3,接收数据
	for(i=0;i<40;i++) //循环接收40位数据
	{
		cnt=0;
		while(DHT11_Read() == 1) //等待低电平到来
		{
			cnt++;
			Delay_us(1);
			if(cnt>100) 
			return 1;//通信超时	
		}
		cnt=0;//下次使用之前先清零
		while(DHT11_Read() == 0) //等待高电平到来
		{
			cnt++;
			Delay_us(1);
			if(cnt>100) 
			return 1;//通信超时	
		}
		Delay_us(30);//延时区分接收到的是0还是1
		if(DHT11_Read() == 1)
		{
			data[i/8] |= 1<<(7-i%8);
		}else
		{
			data[i/8] &= ~(1<<(7-i%8));
		}
	}
	//4,判断数据是否准确
	if(data[0]+data[1]+data[2]+data[3] == data[4])
	{
		dht11.Tem = data[2];
		dht11.Hum = data[0];
		if((data[3] & 1<<7) != 0)//判断温度是否是零下
		{
			dht11.Tem = -dht11.Tem;
		}
		return 0;
	}else
	{
		//printf("数据校验失败\r\n");
		return 2;
	}
}

前提条件是有delay函数stm32f10x延时函数

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值