DHT11简介
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DHT11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则
相比于 DS18B20 只能测量温度,DHT11 既能检测温度又能检测湿度,不过 DHT11 的精度和测量范围都要低于 DS18B20,其温度测量范围为 0~50℃,误差在±2℃;湿度的测量范围为 20%~90%RH(Relative Humidity 相对湿度—指空气中水汽压与饱和水汽压的百分比),误差在±5%RH。DHT11 电路很简单,只需要将 DATA 引脚连接单片机的一个 I/O 即可,不过该引脚需要上拉一个 5K 的电阻,DHT11 的供电电压为 3~5.5V。
开发DHT11
总时序
复位时序
主机发送复位信号
DHT11 的初始化过程同样分为复位信号和响应信号。首先主机拉低总线至少 18ms,然后再拉高总线,延时 20~40us,取中间值 30us,此时复位信号发送完毕。
从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。
响应信号
DHT11 发送响应信号
DHT11 检测到复位信号后,触发一次采样,并拉低总线 80us 表示响应信号,告诉主机数据已经准备好了;然后 DHT11 拉高总线 80us,之后开始传输数据。如果检测到响应信号为高电平,则 DHT11 初始化失败,请检查线路是否连接正常。当复位信号发送完毕后,如果检测到总线被拉低,就每隔 1us 计数一次,直至总线拉高,计算低电平时间;当总线被拉高后重新计数检测 80us 的高电平。如果检测到响应信号之后的80us 高电平,就准备开始接收数据。实际上 DHT11 的响应时间并不是标准的 80us,往往存在误差,当响应时间处于 20~100us 之间时就可以认定响应成功。
数据传输
DHT11 在拉高总线 80us 后开始传输数据。每 1bit 数据都以 50us 低电平时隙开始,告诉主机开始传输一位数据了。DHT11 以高电平的长短定义数据位是 0 还是 1,当 50us 低电平时隙过后拉高总线,高电平持续 26~28us 表示数据“0”;持续 70us 表示数据“1”。\n\n当 最后 1bit 数据传送完毕后,DHT11 拉低总线 50us,表示数据传输完毕,随后总线由上拉电阻拉高进入空闲状态。
dht11.h+dht11.c
#ifndef _dht11_H
#define _dht11_H
#include "system.h"
#define DHT11_H GPIO_SetBits(GPIOB, GPIO_Pin_5)
#define DHT11_L GPIO_ResetBits(GPIOB, GPIO_Pin_5)
#define DHT11_Read_Data GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5)
#define DHT11_PORT GPIOB
#define DHT11_DAT_PIN GPIO_Pin_5
extern u8 rec_data[4];
void DHT11_Init_Out();
void DHT11_Init_In();
void DHT11_Start();
char DHT11_Rec_Byte();
void DHT11_Rec_Data();
#endif
#include "dht11.h"
#include "SysTick.h"
u8 rec_data[4];
void DHT11_Init_Out()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=DHT11_DAT_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT,&GPIO_InitStructure);
}
void DHT11_Init_In()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin=DHT11_DAT_PIN;
GPIO_Init(DHT11_PORT,&GPIO_InitStructure);
}
void DHT11_Start()
{
DHT11_Init_Out();
DHT11_H;
DHT11_L;
delay_ms(24);//至少拉低18ms
DHT11_H;
delay_us(30);//延时20-40us
DHT11_Init_In();
}
char DHT11_Rec_Byte()//接收1个字节
{
u8 i=0;
u8 data=0;
u8 t=0;
for(i=0;i<8;i++)
{
while(DHT11_Read_Data==0);
delay_us(30);
data<<=1;
if(DHT11_Read_Data==1)
data |=1;
while(DHT11_Read_Data==1);
}
return data;
}
void DHT11_Rec_Data()//接收数据
{
char R_L,R_H,T_L,T_H;
char RL,RH,TL,TH,CHECK;
DHT11_Start();
DHT11_H;
if(DHT11_Read_Data==0)//判断响应信号
{
while(DHT11_Read_Data==0);
while(DHT11_Read_Data==1);
R_H=DHT11_Rec_Byte();
R_L=DHT11_Rec_Byte();
T_H=DHT11_Rec_Byte();
T_L=DHT11_Rec_Byte();
CHECK=DHT11_Rec_Byte();
DHT11_L;//拉低总线
delay_us(55);
DHT11_H;//拉高总线
if((R_H+R_L+T_H+T_L)==CHECK)
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
}
rec_data[0]=RH;
rec_data[1]=RL;
rec_data[2]=TH;
rec_data[3]=TL;
}
}
main.c
#include "stm32f10x.h"
#include "led.h"
#include "system.h"
#include "SysTick.h"
#include "beep.h"
#include "key.h"
#include "exti.h"
#include "time.h"
#include "pwm.h"
#include "usart.h"
#include "stdio.h"
#include "iwdg.h"
#include "wwdg.h"
#include "input.h"
#include "touch_key.h"
#include "wkup.h"
#include "adc.h"
#include "adc_temp.h"
#include "lsens.h"
#include "dac.h"
#include "dma.h"
#include "rtc.h"
#include "at24cxx.h"
#include "i2c.h"
#include "ds18b20.h"
#include "hwjs.h"
#include "rs485.h"
#include "can.h"
#include "tftlcd.h"
#include "picture.h"
#include "spi.h"
#include "flash.h"
#include "in_flash.h"
#include "dht11.h"
extern u8 rec_data[4];
int main()
{
u8 i=0;
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组
LED_Init();
USART1_Init(115200);
while(1)
{
i++;
if(i%20==0)
{
LED1=!LED1;
}
if(i%50==0)
{
DHT11_Rec_Data();
printf("温度:%d℃\r\n",rec_data[2]);
printf("湿度:%d\r\n",rec_data[0]);
}
delay_ms(20);
}
}