一、概述
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通 空调;汽车;消费品;气象站;湿度调节器;除湿器;家电;医疗;自动控制
接线:
二、逻辑分析-检测DHT响应信号
LCD1602和DH11都是非标准协议,也就是,去看时序,按照时序写代码
a :dth = 1
b:dth = 0
b-c = 延时30ms
c:dth = 1
c-e 40us+80us = 120us/2 = 60us 取60us用来检测DHT是否响应信号了
取60us==0?
注意:
DHT1 1的供电电压为 3- 5. 5V。传感器上电后,要等待 1 s 以越过不稳定状态在此 期间无需发送任何指令。
代码如下:
#include "reg52.h"
#include "intrins.h"
sbit D5 = P3^7;
sbit dht = P3^3;
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay30ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 2;
j = 67;
k = 183;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay60us() //@11.0592MHz
{
unsigned char i, j;
i = 1;
j = 162;
do
{
while (--j);
} while (--i);
}
void check_DHT(){//看时序图写代码
dht = 1;
dht = 0;
Delay30ms();
dht = 1;
Delay60us();
if(dht == 0){//说明模块响应了,点亮D5
D5 = 0;
}
}
void main()
{
D5 = 1;
Delay1000ms();
check_DHT();
while(1);//程序不退出
}
三、逻辑分析-得到温湿度的数据
a : dht = 1
b :dht = 0
延时30ms
c: dht = 1
卡d点;while(dht1);
卡e点 while(!dht)
卡f点:while(dht)
卡g点:while(!dht)
有效数据都是高电平,持续时间不一样,50us读,低电平0 高电平
传输0的时序分析
传输1的时序分析
由上图可知,当检测g点后的大概50us的时候,是高电平还是低电平就知道传输的是1还是0.
#include "reg52.h"
#include "intrins.h"
sbit D5 = P3^7;
sbit dht = P3^3;
char datas[5];
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay30ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 2;
j = 67;
k = 183;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay60us() //@11.0592MHz
{
unsigned char i, j;
i = 1;
j = 162;
do
{
while (--j);
} while (--i);
}
void DHT11_Start(){//看时序图写代码
dht = 1;
dht = 0;
Delay30ms();
dht = 1;
while(dht);
while(!dht);
while(dht);
}
void Read_Data_From_DHT(){
int i;//轮
int j;//每一轮读多少次
char tmp;//进行移位,用来获取下面的位
char flag;
DHT11_Start();
for(i=0;i<5;i++){//五轮
for(j=0;j<8;j++){//每一轮八次
while(!dht);//等待卡G点
Delay60us();
if(dht == 1){
flag = 1;//高电平
while(dht);
}else{
flag = 0;//低电平
}
tmp = tmp <<1;//tmp等于tmp左移一位
tmp |= flag;//把新得到的数放到尾巴,就是逐渐的把得到的数据放到tmp里面
}
datas[i] = tmp;//把tmp得到的5个8位的值赋值到datas数组中
}
}
void main()
{
D5 = 1;
Delay1000ms();
while(1){//程序不退出
Delay1000ms();
Read_Data_From_DHT();
}
}
四、利用串口显示出温湿度
首先通过温湿度传感器传出来的数值,在上位机中,是化成了二进制的形式传输的,会看成字符型,比如温度是97,那么传给串口接收到的信息就是二进制的0110 0001,串口会输出数据为a,这样并不方便我们观察,所以,需要把ACILL值换成数字,数字1+48 = 49(字符1),故数字0-9与字符0-9差了48。
思路:当我们接收到数值之后,比如32,就把3拿出来,变成字符3,再把2拿出来变成字符2,再传给上位机。这样上位机接收到的就是字符型的数据,就可以直接传输。
#include "reg52.h"
#include "intrins.h"
sbit D5 = P3^7;
sbit dht = P3^3;
sfr AUXR = 0X8e;
char datas[5];
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay30ms() //@11.0592MHz
{
unsigned char i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
void UartInit(void)
{
AUXR = 0x01;//提升EMI信号
SCON = 0X40;//1、配置串口工作方式,REN能接收
TMOD &= 0XF0;
TMOD |= 0X20;//2、配置定时器1 工作方式:8位自动重载
TH1 = 0XFD;//3、计算9600波特率的初值
TL1 = 0XFD;
TR1 = 1;//4、启动定时器
}
void sendByte(char data_msg){
SBUF = data_msg;
while(!TI);//初值TI=0,置位后TI=1,此时请求中断
TI =0;//手动置位
}
void sendString(char* str){
while(*str != '\0')
{
sendByte(*str);
str++;
}
}
void DHT11_Start(){//看时序图写代码
dht = 1;
dht = 0;
Delay30ms();
dht = 1;
while(dht);
while(!dht);
while(dht);
}
void Delay40us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 15;
while (--i);
}
void Read_Data_From_DHT(){
int i;//轮
int j;//每一轮读多少次
char tmp;//进行移位,用来获取下面的位
char flag;
DHT11_Start();
for(i=0;i<5;i++){//五轮
for(j=0;j<8;j++){//每一轮八次
while(!dht);//等待卡G点
D5 = 0;
Delay40us();
if(dht == 1){
flag = 1;//高电平
while(dht);
}else{
flag = 0;//低电平
}
tmp = tmp << 1;//tmp等于tmp左移一位
tmp |= flag;//把新得到的数放到尾巴,就是逐渐的把得到的数据放到tmp里面
}
datas[i] = tmp;//把tmp得到的5个8位的值赋值到datas数组中
}
}
void main()
{
D5 = 1;
UartInit();
Delay1000ms();
while(1){//程序不退出
Delay1000ms();
Read_Data_From_DHT();
sendString("SD:");
sendByte(datas[0]/10 + 0x30);//湿度整数位,提出十位
sendByte(datas[0]%10 + 0x30);//提出个位
sendByte('.');
sendByte(datas[1]/10 + 0x30);//湿度的小数位,提出十位
sendByte(datas[1]%10 + 0x30);//提出个位
sendString("\r\n");//做个换行
sendString("WD:");
sendByte(datas[2]/10 + 0x30);//温度的整数位,提出十位
sendByte(datas[2]%10 + 0x30);//提出个位
sendByte('.');
sendByte(datas[3]/10 + 0x30);//温度的小数位,提出十位
sendByte(datas[3]%10 + 0x30);//提出个位
sendString("\r\n");//做个换行
}
}