一.传感器介绍
1.基本介绍
DHT11数字温湿度传感器是一种具有校准数字信号输出的温湿度传感器。采用特殊的数字模块采集技术和温湿度传感技术,确保产品具有高可靠性和优异的长期稳定性。
应用平台:
暖通空调 测试和测试设备 汽车 数据记录器 消费品 自动控制等
2.管脚说明
管脚 | 作用 |
Vcc | 模块电源正极(电源电压范围:3-5.5V) |
gnd | 管脚的模块数据传输 |
GND | 负极模块供电 |
3.data数据接口串行数据传输
完整的数据传输需要40次bit数据,高位先出
传输的具体过程如下: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(); //延迟70左右us,用于判断是否处于低电平 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; /// TMOD |= 0x20; ///设定时间18位自动重新安装 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; } }