温湿度传感器DHT11的使用
DHT11数据传输的总时序图如下:
开始传输数据前的信号时序图
数据接收时的时序图
DHT11与单片机的连接图
从DHT11读取数据的代码编写步骤:
1-初始化单片机和DHT11连接的PE2口
2-配置PE2口的输入输出模式函数
3-配置8位接收数据函数,根据DHT11数据传输时序图编写
4-建立数据存储变量,根据总是时序图编写从DHT11上接收数据函数
例程:
bsp_dht11.c文件
#include "bsp_dht11.h"
#include "bsp_systick.h"
/*==================1-初始化单片机和DHT11连接的PE2口======================*/
void DHT11_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStruct;
RCC_AHB1PeriphClockCmd(DHT11_CLK, ENABLE);
GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(DHT11_PORT,&GPIO_InitStruct);
}
/*=================2-配置GPIO口的输入模式函数=========================*/
static void DHT11_Mode_IPU(void)
{
GPIO_InitTypeDefGPIO_InitStruct;
RCC_AHB1PeriphClockCmd(DHT11_CLK, ENABLE);
GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(DHT11_PORT,&GPIO_InitStruct);
}
/*=================2-配置GPIO口的输出模式函数=========================*/
static void DHT11_Mode_OUT_PP(void)
{
GPIO_InitTypeDefGPIO_InitStruct;
RCC_AHB1PeriphClockCmd(DHT11_CLK, ENABLE);
GPIO_InitStruct.GPIO_Pin = DHT11_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(DHT11_PORT,&GPIO_InitStruct);
}
/*=================3-配置8位接收数据函数,根据DHT11数据传输时序图编写=====================*/
static uint8_t Read_Byte(void)
{
uint8_t i,temp;
for(i=0;i<8;i++)
{
/*每一个bit都是以50us的低电平开始,等电平置高,则跳出循环*/
while(DHT11_DATA_IN() == Bit_RESET );
/*‘0’表示的置高时间过短,可直接判断‘1’表示的时间,但滞留时间不宜过长,以防跳出下一位的开始时间*/
Delay_us(35);
if(DHT11_DATA_IN() == Bit_SET )
{
/*等待跳出‘1’置高表示的时间*/
while(DHT11_DATA_IN()== Bit_SET);
/*把第(7-i)位置 '1'*/
temp|=(uint8_t)(0x01<<(7-i));
}
else
{
/*把第(7-i)位置 '0'*/
temp&=(uint8_t)~(0x01<<(7-i));
}
}
return temp;
}
/*=================4-根据总时序图编写接收数据函数===================================*/
uint8_t Read_DHT11(DHT11_Data_TypeDef*DHT11_Data)
{
uint16_t count;
/*将主机设为输出模式*/
DHT11_Mode_OUT_PP();
/*将主机拉低*/
DHT11_DATA_OUT(DHT11_LOW);
/*配置主机拉低时间,至少拉低18ms*/
Delay_ms(18);
/*将主机拉高*/
DHT11_DATA_OUT(DHT11_HIGH);
/*配置主机拉高时间*/
Delay_us(30);
/*将主机设置为输入模式*/
DHT11_Mode_IPU();
if(DHT11_DATA_IN()== Bit_RESET)
{
count=0;
/*等待DHT11置低响应结束,达到一定时间后,响应失败,返回0*/
while(DHT11_DATA_IN()== Bit_RESET)
{
count++;
if(count> 1000) return 0;
}
count=0;
/*等待DHT11置高响应结束,达到一定时间后,响应失败,返回0*/
while(DHT11_DATA_IN()== Bit_SET)
{
count++;
if(count> 1000) return 0;
}
/*开始接收数据*/
DHT11_Data->humi_int=Read_Byte();
DHT11_Data->humi_deci=Read_Byte();
DHT11_Data->temp_int=Read_Byte();
DHT11_Data->temp_deci=Read_Byte();
DHT11_Data->check_sum=Read_Byte();
/*读取结束,将主机设为输出模式*/
DHT11_Mode_OUT_PP();
/*主机拉高*/
DHT11_DATA_OUT(DHT11_HIGH);
/*检查读取的数据是否正确*/
if(DHT11_Data->check_sum== DHT11_Data->humi_int + DHT11_Data->humi_deci +DHT11_Data->temp_int+ DHT11_Data->temp_deci)
return 1;
else
return 0;
}
else
return 0;
}
bsp_dht11.h文件
#ifndef __BSP_DHT11_H
#define __BSP_DHT11_H
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#define DHT11_HIGH 1
#define DHT11_LOW 0
#define DHT11_CLK RCC_AHB1Periph_GPIOE
#define DHT11_PIN GPIO_Pin_2
#define DHT11_PORT GPIOE
#define DHT11_DATA_IN() GPIO_ReadInputDataBit(DHT11_PORT,DHT11_PIN)
#define DHT11_DATA_OUT(a) if (a) \
GPIO_SetBits(DHT11_PORT,DHT11_PIN);\
else \
GPIO_ResetBits(DHT11_PORT,DHT11_PIN)
/*定义一个结构体,储存从DHT11读取的数据*/
typedef struct
{
uint8_t humi_int; //湿度的整数部分
uint8_t humi_deci; //湿度的小数部分
uint8_t temp_int; //温度的整数部分
uint8_t temp_deci; //温度的小数部分
uint8_t check_sum; //校验和
}DHT11_Data_TypeDef;
void DHT11_GPIO_Config(void);
uint8_t Read_DHT11(DHT11_Data_TypeDef*DHT11_Data);
#endif /*__BSP_DHT11_H*/