DHT11读取历程

一整体介绍

查看芯片手册,最重要的是要根据手册了解,相应的知识,例如:芯片功能,芯片管脚及功能

以及数据如何读等等;

DHT11读取历程_第1张图片

这里需要注意是数字传感器,传出的数据是数字信号,像模拟传感器,传出的就是模拟信号

需要ADC接收转换为数字信号,计算为我们需要的数据。

DHT11温湿度传感器,一种基于单总线通信的传感器模块。

DHT11读取历程_第2张图片

对于单总线而言,主要通过改变DQ的电平状态根据时间进行相应的操作;

查看手册可以发现引脚定义图:

其中的DATA也就是DQ引脚;

DHT11读取历程_第3张图片

其余属于基本引脚,供电,共地引脚等等。

产品参数介绍。介绍了对于湿度,温度在出产时,25°,5v电压下的测量性能;

(对于数据测量有精度要求可以仔细研读)

以及一些测量的电气特性介绍:如工作电压,工作电流,采样周期需要多久;

(需要特别注意采样周期,一般来说数字传感器测量数据无论时I2C还是SPI都需要一定的时间。也就是采样时间);

DHT11读取历程_第4张图片

二读取历程:

这里单线双向的意思就是通信双方都可以根据,这根线进行信息交互。

类似于我们I2C当中主机从机交换数据线控制权。

DHT11读取历程_第5张图片

电路接线要求:单总线通常要求外接一个约 4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平
数据发送一次一共 40bit 数据分为
8位湿度整数int+8位湿度小数crsi+8位温度整数int+8位温度小数crsi+8位校验位

需要注意这里的校验位,等于前面接收的四位8位二进制数据的和,否则数据接收错误;

也就是8位湿度整数int+8位湿度小数crsi+8位温度整数int+8位温度小数crsi=8位校验位;

也就是的单总线DHT11的检验方式。等式不成立即数据读取错误:

手册当中也有例子如下:

DHT11读取历程_第6张图片

下面就是对于单通信的起始信号,响应信号,数据格式,校验位的介绍

DHT11读取历程_第7张图片

手册当中的时序图如下:

1.总过程:

DHT11读取历程_第8张图片

2.起始信号:

总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后, 等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束 后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换 到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。

DHT11读取历程_第9张图片

2.数据传输:

其中0和1数据传输要求时间不同;

手册当中分开传送

总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。
数据0:

DHT11读取历程_第10张图片

数据1:

DHT11读取历程_第11张图片

下面时基于STM32F10X标准库函数写的读取历程:

DHT11.h

#ifndef __DHT11_H
#define __DHT11_H
#include "stm32f10x.h"                  // Device header
#include "Serial.h"
#include "Delay.h"
#include "stdio.h"
#define DHT11_CLK     		RCC_APB2Periph_GPIOC
#define DHT11_CLK_INIT		RCC_APB2PeriphClockCmd
#define DHT11_PORT				GPIOC
#define	DHT11_PIN					GPIO_Pin_1

typedef enum{
	MODE_IN = 0,
	MODE_OUT = 1,
}DHT11_MODE;


#define DHT11_HIGH()	GPIO_SetBits(DHT11_PORT,DHT11_PIN)
#define DHT11_LOW()		GPIO_ResetBits(DHT11_PORT,DHT11_PIN)

#define DHT11_ReadPin()		(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))

typedef struct {  
    uint8_t Tem_H;   // 存储从DHT11读取整数温度数据 
    uint8_t Tem_L;   // 存储从DHT11读取小数温度数据  
    uint8_t Hum_H; // 存储从DHT11读取整数湿度数据  	
    uint8_t Hum_L; // 存储从DHT11读取小数湿度数据  
}DHT11_TyDef;

void Change_Dht11Mode(DHT11_MODE flag);
uint8_t Dht11_ReadData(DHT11_TyDef * data);

#endif


DHT11.C文件

#include "DHT11.h"
void Dht11_Config(void)
{
	Change_Dht11Mode(MODE_OUT);
	DHT11_HIGH();
}

void Change_Dht11Mode(DHT11_MODE flag)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
  DHT11_CLK_INIT(DHT11_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
	if(flag == 1)
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	else
	{
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	}
  GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}


uint8_t Dht11_ReadData(DHT11_TyDef * data)
{
	uint8_t retury = 0;
	uint8_t i = 0;
	uint8_t Data[5] = {0};
	
	Dht11_Config();
	
	//发送起始信号
	DHT11_LOW();
	Delay_ms(18);
	DHT11_HIGH();
	
	Change_Dht11Mode(MODE_IN);
	
	//等待DHT11响应
	while(DHT11_ReadPin())
	{
		retury++;
		Delay_us(1);
		if(retury > 100)	return 0;
	}
	retury = 0;
	//等待响应结束
	while(DHT11_ReadPin() == 0)
	{
		retury++;
		Delay_us(1);
		if(retury > 100)	return 0;
	}
	retury = 0;
	
	for(i=0; i<40; i++)
	{
		//判断低电平是否到来
		while(DHT11_ReadPin())
		{
			retury++;
			Delay_us(1);
			if(retury > 100)	return 0;
		}
		retury = 0;	
		//等待低电平结束
		while(DHT11_ReadPin() == 0)
		{
			retury++;
			Delay_us(1);
			if(retury > 100)	return 0;
		}
		retury = 0;	
		
		Delay_us(30);
	//判断数据
		if(DHT11_ReadPin())//收到数据1
		{
			Data[i/8] |= (1<<(7-i%8));
		}
		else
		{
			Data[i/8] &= ~(1<<(7-i%8));
		}
	}
	//校验位计算
	if(Data[4] == Data[0]+Data[1]+Data[2]+Data[3])
	{
		data->Hum_H = Data[0];
		data->Hum_L = Data[1];
		data->Tem_H = Data[2];
		data->Tem_L = Data[3];
		return 1;
	}
	else
	{
		Serial_Printf("Dht11 Err\r\n");
		return 0;
	}
}

后续还提供了一种写法.

你可能感兴趣的:(单片机,嵌入式硬件)