微处理器与 DHT11之间的通讯采用单总线通信,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数
部分用于以后扩展,现读出为零.操作流程如下:
一次完整的数据传输为40bit,高位先出。
数据格式:
8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于
“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”
所得结果的末8位。
通讯过程:
流程如下
产生起始信号(空闲的时候要把总线拉高):
1)总线空闲状态为“高电平”,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。之后需要把总线变为空闲状态,让DHT11可以通知你。(电平的跳变通知DHT11,给DHT11一定的反应时间让它知道你要和它通信了)
2)DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us“低电平响应信号”。(DHT11知道你要和它通信,它告诉你它收到你的请求,可以和你通信了)
3)主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号(你接收它告诉你的消息,看它是否可以和你通信(总线为低电平,说明DHT11发送响应信号,如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常),并等待它就绪)
4)等待DHT11释放总线(释放之后你就可以给它发消息了,DHT11发送响应信号后,再把总线
拉高80us,准备发送数据)
主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。
//产生起始信号
u8 DHT11_Stat(void)
{
u8 time = 0;
//1)产生起始信号
DHT11_OUT(1);
Delay_us(10);
DHT11_OUT(0);
Delay_ms(20);
DHT11_OUT(1);
time = 0;
// 2)、3)等待应答
while(DHT11_IN != 0){
Delay_us(1);
time++;
if(time ==100)
return 1;
}
time = 0;
// 4)等待DHT11释放总线
while(DHT11_IN != 1){
Delay_us(1);
time++;
if(time ==100)
return 1;
}
return 0;
}
发送数据:
1)每一bit数据都以50us低电平时隙开始
2)高电平的长短定了数据位是0还是1.
3)当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
格式见下面图示.
数字0信号表示方法:
数字1信号表示方法:
```bash
//读取并处理数据
u8 DHT11_ReadData(float *temp,float *hum)
{
u8 time = 0;
u8 i, j;
u8 data[5] = {0};
if(DHT11_Stat())
return 1;
for(i = 0;i<=4;i++)
for(j = 0;j<8;j++){
time = 0;
while(DHT11_IN != 0){// 3) 最后一bit数据传送完毕后
Delay_us(1);
time ++;
if(time == 100)
return 1;
}
time = 0;
while(DHT11_IN != 1){// 1) 等待本次数据开始发送
Delay_us(1);
time ++;
if(time == 100)
return 1;
}
// 2) 判断数字信号为0还是1
Delay_us(30); //26-28us为0,大于70us为1
if(DHT11_IN)//判断数据位0/1
data[i] |= 1<<(7-j);
else
data[i] &= ~(0x01<<(7-j));
}
//校验
if(data[4] == data[0]+data[1]+data[2]+data[3]){
*hum = data[0]+data[1]/10.0;
*temp = data[2]+data[3]/10.0;
}
else
printf("Check the error\r\n");
return 0;
}