DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次 通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数 部分用于以后扩展,现读出为零.操作流程如下: 一次完整的数据传输为40bit,高位先出。
数据格式:数据格式:8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
数据传送正确时校验和数据等于“
8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据”
所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主 机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集, 如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后 转换到低速模式。
![](https://img-blog.csdnimg.cn/d71cfc7f4c6444a3bacba94a3c98c203.png)
总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必 须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后, 等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束 后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换 到输入模式,或者输出高电平均可, 总线由上拉电阻拉高
![](https://img-blog.csdnimg.cn/2d399cf6f3db47dda1dcd24bd3517c5b.png)
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉 高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定 了数据位是0还是1.格式见下面图示.如果读取响应信号为高电平,则DHT11没有 响应,请检查线路是否连接正常.当最后一bit数据传送完毕后,DHT11拉低总线 50us,随后总线由上拉电阻拉高进入空闲状态。
![](https://img-blog.csdnimg.cn/8816fdb0f08a4bc88c242114ba0ed1a6.png)
![](https://img-blog.csdnimg.cn/ea5d6b99bbea4b588f523fd4f5de24c2.png)
ps:
总线拉低18微妙是为了触发DH11能检测到起始信号,DH11检测到起始信号后,等待主机发起开始信号结束(主机拉高20-40us),之后引脚转为输入模式,然后DH11发送80us的低电平响应信号,之后DH11再把总线拉高80us准备发送数据,发送数据是根据高电平的长短来确定是1还是0,发送完一位数据后,都要把总线拉低50us的间隙 之后再发下一位。
#include<stdio.h>
#include<wiringPi.h>
#define PIN 11
int main()
{
int i,j;
unsigned long databuf = 0; //存放温湿度内存
unsigned char crc = 0;
//初始化wiringPi库
if(wiringPiSetup() == -1)
{
printf("error wiringPi init\n");
return -1;
}
//初始化引脚的工作模式
pinMode(PIN,OUTPUT);
//初始化总线,拉高电平(只对这个温湿度而言,其它根据引脚的功能而定)
digitalWrite(PIN,HIGH);//init
while(1)
{
delay(3000);
pinMode(PIN,OUTPUT);
digitalWrite(PIN,LOW);//拉低电平,延时25ms(t1时刻),触发DH11起始信号(叫它准备工作)
delay(25);
digitalWrite(PIN,HIGH);//拉高电平,延时27us(t2时刻),主机开始发起结束信号
//delayMicroseconds(27);
pinMode(PIN,INPUT); //设置为输入模式
pullUpDnControl(PIN, PUD_UP);//启用上拉电阻,将不稳定的信号设为高电平,以免干扰
delayMicroseconds(27);
if (digitalRead(PIN) == 0) //dh11拉低电平,延时80us(t3时刻),(功能:向主机发起响应信号)
{
while(!digitalRead(PIN)) //等待高电平(t4时刻)
;
//dh11初始化成功(获得数据)
//开始传输前32位温湿度数据
for(i=0;i<32;i++)
{
while(digitalRead(PIN)) //等待低电平(t5时刻)
;
while(!digitalRead(PIN))//等待高电平(t6时刻)高电平的响应时长来判断是1或0
;
delayMicroseconds(32);
databuf *=2; //左移一位(左高右低)
if(digitalRead(PIN)==HIGH)//延时32us后还是高电平 说明是1
{
databuf++; //是1databuf加一
}
}
//开始传输最后八位校验位
for(i=0;i<8;i++)
{
while(digitalRead(PIN))//等待低电平(类t5时刻)
;
while(!digitalRead(PIN))/等待高电平(类t6时刻)高电平的响应时长来判断是1或0
;
delayMicroseconds(32);
crc *=2;
if(digitalRead(PIN)==HIGH)//延时32us后还是高电平 说明是1
{
crc++;
}
}
}
//发送是先发低位依次到高位,高位还是高位,低位是否是低位,具体看大端还是小端模式
//dh11前八位是湿度整数(最低位),之后八位是小数,在之后八位是温度整数,在之后八位是温度小数,最后八位是校验位(最高位),跟我们平时的读写习惯相反,左高又低
//字节序较高位储存在字节序较低位,所以湿度整数存储在最低位,进行与运算有1的都为1,为0的都为零
printf("RH:%d.%d\n",(databuf>>24) & 0xff,(databuf>>16) & 0xff);
printf("TMP:%d.%d\n",(databuf>>8) & 0xff,databuf & 0xff);
databuf = 0;
}
return 0;
}
运行结果:
大端模式(Big-Endian):是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
小端模式(Little-Endian):是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。数据的存储方向和我们的阅读习惯(方向)不一致。