目录
一、DTH11介绍
①:简介
DATA用于微处理器与DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,小数部分用于以后扩展,现读出为零。
数据格式:8bit湿度整数数据+8bit湿度小数数据+8bit温度整数数据+8bit温度小数数据+8bit校验和。
②:总时序图
(1)工作总时序
(2) 数据通信开始时序
解读:总线空闲状态为高电平,总线拉低必须大于18毫秒,发出开始的信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可。总线拉高,主机等待DHT11响应DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号,主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号。
(3)数据0信号时序
(4)数据1信号时序
解读:
总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短判断数据位是0还是1。最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
二、硬件原理图
三、软件代码
/*
功能:树莓派获取室内温湿度
*/
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long uint32;
int pinNumber = 29;
void pi_sendstartsingnal(void)
{
pinMode(pinNumber,OUTPUT);
digitalWrite(pinNumber, 1);
delayMicroseconds(10);
digitalWrite(pinNumber, 0);
delay(30);
digitalWrite(pinNumber, 1);
delayMicroseconds(30);
pinMode(pinNumber, INPUT);
pullUpDnControl(pinNumber,PUD_UP);
}
/*获取数据*/
int32_t dht11_read_data(uint8_t *pdht11_data)
{
uint8_t data=0;
uint8_t *p = pdht11_data;
int32_t i=0,j=0;
uint32_t check_sum=0;
int32_t dht11_level_cnt=0;//超时计数器
pi_sendstartsingnal();
//1.等待Pin9的电平变为低电平
dht11_level_cnt=0;
while(digitalRead(pinNumber))//添加超时处理
{
dht11_level_cnt++;
delayMicroseconds(1);
if(dht11_level_cnt >= 4000)
{
return -1;
}
}
//2.测量Pin9引脚低电平持续的时间
dht11_level_cnt=0;
while(!digitalRead(pinNumber))//超时判断电平的合法性
{
dht11_level_cnt++;
delayMicroseconds(1);
if(dht11_level_cnt >= 100)
{
return -2;
}
}
//3.测量Pin9引脚高电平持续的时间
dht11_level_cnt=0;
while(digitalRead(pinNumber))//超时判断电平的合法性
{
dht11_level_cnt++;
delayMicroseconds(1);
if(dht11_level_cnt >= 100)
{
return -3;
}
}
//循环接收5个字节
for(j=0;j<5; j++)
{
//进行正常一个字节接收
for(data=0,i=7; i>=0; i--)
{
//1.判断每个数据0/数据1
dht11_level_cnt=0;
while(digitalRead(pinNumber)==0)
{
dht11_level_cnt++;
delayMicroseconds(1);
if(dht11_level_cnt >= 100)
{
return -4;
}
}
//2.延时40us左右(50us+40us=90us)数据0与数据1的划分时间:78us
delayMicroseconds(30);
//3.判断当前引脚的电平
if(digitalRead(pinNumber))
{
data|=1<<i;//高位优先传输
dht11_level_cnt=0;
while(digitalRead(pinNumber))//超时处理等待高电平持续完毕
{
dht11_level_cnt++;
delayMicroseconds(1);
if(dht11_level_cnt >= 50)
{
return -5;
}
}
}
}
p[j]=data;
}
//数据结束可以忽略,延时100us
delayMicroseconds(100);
//4.进行校验和
check_sum=(p[0]+p[1]+p[2]+p[3])&0xFF;
if(check_sum != p[4])
return -6;
return 0;
}
int main(void)
{
uint8_t buf[4]={0};
int32_t rt=0;
if(wiringPiSetup()==-1)
{
return 1;
}
pinMode(pinNumber,OUTPUT);
digitalWrite(pinNumber, 1);
while(1)
{
rt = dht11_read_data(buf);
if(!rt)
{
printf("OK!\n");
printf("RH:%d.%dC\n",buf[2],buf[3]);
printf("TMP:%d.%d\n",buf[0],buf[1]);
}
else
{
printf("dht11 read error,code = %d\r\n",rt);
}
//两次测量间隔要设置合理时间ms
delay(3000);
}
return 0;
}