1. DHT11简介:
是广州奥松有限公司生产的一款湿温度一体化的数字传感器,广泛应用于各种需要测量温度
和湿度的场景,例如智能家居、气象站、环境监测等领域。
2. DHT11性能指标和特性:
工作电压范围
|
3.5V-5.5V
|
工作电流
|
平均 0.5mA
|
湿度测量范围
|
20-90%RH
|
温度测量范围
|
0-50℃
|
湿度分辨率
|
1%RH
|
温度分辨率
|
1℃
|
采样周期
|
1S
|
单总线结构
|
单总线通信
|
与 TTL 兼容
|
5V
|
3. 电路连接说明:
在数据端和电源 正之间接一只 4.7K 的上拉电阻。
为什么要接上拉电阻?--------是为了提高稳定性
下图是加了4.7k上拉电阻后,示波接接收DHT11发送的一帧数据。
很明显,数据信号未出现毛刺、抖动等现象。
下图是没有加4.7k上拉电阻,示波接接收DHT11发送的一帧数据。
很明显,数据信号出现出现失真、毛刺、抖动等现象。
所以为保证接收数据的稳定性,需要在数据端和电源正之间接一只 4.7K 的上拉电阻。
4. DHT11数据格式:
湿度整数数据
|
湿度小数数据
|
温度整数数据
|
温度小数数据
|
校验和
|
8位 | 8位 | 8位 | 8位 | 8位 |
1(bit)-8(bit) | 9(bit)-16(bit) | 17(bit)-24(bit) | 25(bit)-32(bit) | 33(bit)-40(bit) |
数据传输实例:
湿度整数数据
|
湿度小数数据
|
温度整数数据
|
温度小数数据
|
校验和
| |
1(bit)-8(bit) | 9(bit)-16(bit) | 17(bit)-24(bit) | 25(bit)-32(bit) | 33(bit)-40(bit) | |
80%湿度 | 30摄氏度 | 80+30=110 | |||
0101 0000 | 0000 0000 | 0001 1110 | 0000 0000 | 0110 | 1110 |
从湿度数据的高位开始传输,直到传输完校验和数据的低位,从1(bit)到40(bit). |
5. DHT11的传输时序:
5.1 主机(单片机)发送读数据请求:
5.1.1 读数据请求时序实现代码:
void DHT11_Start(void)
{
DHT11_Data_Line=0; //引脚拉低
Delay20ms(); //延时20ms
DHT11_Data_Line=1; //引脚拉高
Delay25us(); //延时25us
}
5.1.2 读数据请求时序解读:
开始信号:
单片机引脚输出低电平(0)至少持续18ms,然后引脚再输出高电平(1)并持续20~40us。
5.2 DHT11发送响应信号:
5.2.1 响应信号实现代码:
uchar DHT11_Check(void)
{
uchar flag=0;
while(DHT11_Data_Line&&(flag<100)) //DHT11_Data_Line:等待低电平到来,flag<100防止陷入
{flag++;} //while死循环,当一定时间flag=100后还未检测到低电平则跳出循环。
if(flag>=100)return 1; //未接收到DHT11的响应信号
else flag=0; //flag清零
while(!DHT11_Data_Line&&(flag<100)) //DHT11_Data_Line:等待高电平到来,flag<100防止陷入
{flag++;} //while死循环,当一定时间flag=100后还未检测到低电平则跳出循环。
if(flag>=100)return 1; //未接收到DHT11的响应信号
else return 0; //接收到DHT11的响应信号
}
5.2.2 响应信号时序解读:
响应信号:
DHT11数据引脚输出低电平(0)至少持续40~50us,然后引脚再输出高电平(1)并持续40~50us。
5.3 单片机接收DHT11输出的1byte信号:
5.3.1 DHT11发送数据“ 0 ”信号:
5.3.2 DHT11发送数据“ 1 ”信号:
5.3.3 DHT11发送数据“0”“ 1 ”信号时序解读:
低电平“ 0 ”持续时间 | 高电平“ 1 ”持续时间 | 区别 | |
数据“ 0 ” | 12~14us | 26~28us |
低电平持续时间相同 高电平持续时间有差别 |
数据“ 1 ” | 12~14us | 116~118us |
数据“ 0 ”信号:
DHT11输出低电平(0)持续12~14us,然后输出高电平(1)26~28us。
数据“ 1 ”信号:
DHT11输出低电平(0)持续12~14us,然后输出高电平(1)116~118us。
输出数据“0”,“1”根据高电平的持续时间来区分。
5.3.4 读取DHT11输出的1byte数据代码:
uchar DHT11_Read_Byte(void)
{
uchar i,dat;
dat=0;
for(i=0;i<8;i++) //循环8次,接收一个字节的数据
{
while(!DHT11_Data_Line); //等待高电平
Delay25us();
Delay25us(); //延时50us
dat<<=1; //dat往左移一位
if(DHT11_Data_Line==1) //延时50us后,判断传输的数据是否为:“ 1 ”
{
dat+=1; //如果传输的数据为 1 ,则dat+1
}
while(DHT11_Data_Line); //等待高电平结束,接收下一位数据
}
return dat; //dat为接收的8位数据。
}
5.4 DHT11发送数据流程图:
第 1 步 | 第 2 步 | 第 3 步 |
单片机发送-开始信号 | DHT11发送-响应信号 | DHT11发送-温湿度数据 |
5.5 读取DHT11的1帧数据的仿真电平信号图:
下图是单片机读取一次DHT11数据的仿真电平信号图
单片机发送开始信号,即图中的编号:1,2
DHT11发送响应信号,即图中的编号:3
DHT11发送40bit数据,即图中的编号:4 ~ 43
从下图的40bit数据电平图可已看出,输出数据“ 1 ”的高电平的持续时间,很明显长于,输出数据“ 0 ”的高电平持续时间。
6. DHT11的protues仿真图:
7. DHT11驱动代码:
7.1 DHT11.c文件:
#include "DHT11.h"
#include "intrins.h"
void Delay20ms() //@11.0592MHz
{
unsigned char i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
void Delay25us() //@11.0592MHz
{
unsigned char i;
i = 9;
while (--i);
}
void DHT11_Start(void)
{
DHT11_Data_Line=0;
Delay20ms();
DHT11_Data_Line=1;
Delay25us();
}
uchar DHT11_Check(void)
{
uchar flag=0;
while(DHT11_Data_Line&&(flag<100)) //?????
{flag++;}
if(flag>=100)return 1;
else flag=0;
while(!DHT11_Data_Line&&(flag<100)) //?????
{flag++;}
if(flag>=100)return 1;
else return 0;
}
uchar DHT11_Read_Byte(void)
{
uchar i,dat;
dat=0;
for(i=0;i<8;i++)
{
while(!DHT11_Data_Line);
Delay25us();
Delay25us();
dat<<=1;
if(DHT11_Data_Line==1)
{
dat+=1;
}
while(DHT11_Data_Line);
}
return dat;
}
uchar DHT11_Read_Data(uchar *temp,uchar *humi)
{
uchar dat[5]={0,0,0,0,0};
DHT11_Start();
if(DHT11_Check()==0)
{
while(DHT11_Data_Line);
dat[0]=DHT11_Read_Byte();
dat[1]=DHT11_Read_Byte();
dat[2]=DHT11_Read_Byte();
dat[3]=DHT11_Read_Byte();
dat[4]=DHT11_Read_Byte();
if((dat[0]+dat[1]+dat[2]+dat[3])==dat[4])
{
*temp=dat[2];
*humi=dat[0];
}
return 2;
}
return 1;
}
7.2 DHT11.h文件:
#ifndef __DHT11_H__
#define __DHT11_H__
#define uchar unsigned char
#define uint unsigned int
#include "reg51.h"
sbit DHT11_Data_Line = P1^0;
void Delay20ms();
void Delay25us();
void DHT11_Start(void);
uchar DHT11_Check(void);
uchar DHT11_Read_Byte(void);
uchar DHT11_Read_Data(uchar *temp,uchar *humi);
#endif
7.3 main.c文件:
#include <reg51.H>
#include "intrins.h"
#include "DHT11.h"
void main()
{
uchar temp,humi;
uchar flag=0;
while(1)
{
flag=DHT11_Read_Data(&temp,&humi);
}
}