一.传感器介绍
1.基本介绍
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度符合传感器,它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性和卓越的长期稳定性。
应用平台:
暖通空调 测试及检测设备 汽车 数据记录器 消费品 自动控制等
2.管脚说明
管脚 | 作用 |
Vcc | 模块供电正极(供电电压范围:3-5.5V) |
gnd | 模块数据传输管脚 |
GND | 模块供电负极 |
3.data数据接口串行数据传输
一次完整的数据传输需要40bit数据,高位先出
传输具体过程如下:8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据 +8bit校验和
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主 机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.
二.数据传输时序图、
1.模块存在检测时序图
流程如下
单片机方面:单片机首先会给模块高电平,然后会将电平拉低,同时延时至少18ms,接着将电平拉高,同时延迟最多40us,可设定30us。
模块方面:模块会将管脚的电平拉低,并延迟80us,如果单片机检测在80us时间内,管脚一直属于低电平,那么就可以判断模块存在。
可以写出如下代码:判断模块是否存在
sbit LED = P2^0;
sbit DATA = P1^0;
void Delay25ms() //@11.0592MHz
{
unsigned char i, j;
i = 45;
j = 208;
do
{
while (--j);
} while (--i);
}
void Delay70us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 29;
while (--i);
void check_DHT11()
{
DATA = 1; //将电平拉高
DATA = 0; //将电平拉低
Delay25ms(); //低电平延迟25ms(至少18ms)
DATA = 1; //延时过后将电平拉高
Delay70us(); //延迟大约70us,用来判断是否处于低电平
if(DATA ==0)
{
LED = 0; //如果一直处于低电平,则模块存在,指示灯点亮
}
}
2.数据读取时序图
(1)数据0时序图
(2)数据1时序图
编程思路:由数据组成可以知道,该组数据由5组构成,每组有8位,因此我们可以建立两个变量,一个是轮数,读取5轮,一个是每轮读取的位数,读取8位。通过时序图可以得知,当data数据变成高电平时,开始进行数据读取,这时可以进行延时大约50us来判断读取的数据,(因为0信号高电平最多28us,而1信号最多70us,因此延迟50us来进行判断),如果经过50us依旧是高电平,则读取数据就是1,由于70us不好把握,因此需要进行“卡电平”,卡出电平降低的点,否则就是0,可以新建一个变量,将读取到的数据进行临时存放,为了保存一组完整的数据,需要新建一个char型变量,用于存储一组变量,这时可以将这个char型变量进行左移,然后将读取过来的“0”、“1”数据和char的地位进行按位与运算,直到将整个char型变量替换完毕,将替换完成的变量存储在数组中,直到整个数组全被存储,这时数据读取完毕。
实现代码如下:
sbit DATA = P1^0;
char save_data[5]; //画出数据存储区域
void Delay50us()
{
unsigned char i;
_nop_();
i = 20;
while (--i);
}
int i; //定义读取的轮数
int j; //定义读取的位数
int tep; //定义一组的临时存储区(8位)
int flag; //定义读取的0、1数据
for(i = 0;i < 5;i ++)
{
for(j = 0;j < 8;j++)
{
while(!DATA); //如果data数据管脚编程高电平,则开始数据传输
Delay50us(); //延迟50us,然后判断data的电平状态
if(DATA == 1)
{
flag = 1;
while(DATA);
}
else
{
flag = 0;
}
tep = tep<<1;
tep |= flag;
}
save_data[i] = tep;
}
三.全代码实现
#include <REGX52.H>
#include <intrins.h>
sbit LED = P2^0;
sbit DATA = P1^0;
char save_data[5]; //画出数据存储区域
void Delay25ms() //@11.0592MHz
{
unsigned char i, j;
i = 45;
j = 208;
do
{
while (--j);
} while (--i);
}
void Delay70us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 29;
while (--i);
}
void Delay50us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 20;
while (--i);
}
/*串口初始化*/
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x40; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
void send_byte(char msg_data)
{
SBUF = msg_data; //将形式参数msg_data传送到SBUF中
}
/*判断温度检测模块是否存在*/
void check_DHT11()
{
DATA = 1;
DATA = 0;
Delay25ms();
DATA = 1;
Delay70us();
if(DATA ==0)
{
LED = 0;
}
}
/*读取温度检测模块发送的数据*/
void send_DHT_data()
{
int i;//轮数
int k;//每轮的位数
char flag;
char tmp;
check_DHT11();
for(i=0;i<5;i++)
{
for(k=0;k<8;k++)
{
while(!DATA);//等待模块在低电平结尾处
Delay50us();//延迟50微秒之后,读取DATA数据,如果依旧是高电平代表1,否则就是低电平,表示0
if(DATA == 1)
{
flag = 1;
while(DATA); //如果是高电平信号,那么就需要卡电平,因为高电平信号会持续将近70微秒
}
else
{
flag = 0;
}
/*通过将DATA的每一位数据把tmp的从低位一直替换到高位,直到替换完毕。*/
tmp = tmp << 1;
tmp |= flag;
}
save_data[i] = tmp;
}
}