- 分析DHT11温湿度传感器的时序图
从时序图中我们可以知道,DHT11 刚开始时是高电平,然后需要拉低电平至少18ms(编程时直接取20ms),再拉高电平电平20-40us,然后DHT会有一个80us的响应信号,我们只要将时间延长至50us,判断引脚是否是低电平就能确定有没有检测到响应信号,当我们检测到响应信号的时候 arduino 就会一直等待,一直到F点的时候,DHT开始发送数据
代码:
void DHT11_Stat()
{
pinMode(PIN,OUTPUT);
digitalWrite(PIN,HIGH);
digitalWrite(PIN,LOW);
delay(20);
digitalWrite(PIN,HIGH);
delayMicroseconds(50);
if(digitalRead(PIN) == LOW){ //检测到响应信号
while(digitalRead(PIN) == LOW);
while(digitalRead(PIN) == HIGH);
Serial.println("yes");
}else{ //未检测到响应信号(模块损坏/未连接)
Serial.println("no");
}
}
开始发送时会有一个50us的等待时间,等待时间过后会升为高电平,如果高电平的持续时间是26-28us那么就发送的是数据0,如果高电平的持续时间是70us那么就发送的是数据1,我们假设H点到G点的时间是35us,那么我们只要判断G点是高电平还是低电平就可以知道发送的是数据0,还是数据1,然后将读到的数据存到变量上,每循环8次就得到一个字节的数据。DHT会发送5个字节的数据,每个字节都代表一些数据,分别是湿度的整数位、湿度的小数位、温度的整数位、温度的小数位、校验码
uint8_t DHT11_readByte()
{
uint8_t i,flag,byteRead=0;
for(i=0;i<8;i++){
while(digitalRead(PIN) == LOW);
delayMicroseconds(35);
if(digitalRead(PIN) == HIGH){ //读到1
flag = 1;
while(digitalRead(PIN) == HIGH);
}else{
flag = 0; //读到0
}
byteRead <<= 1; //每循环一次byteRead移动1位
byteRead |= flag; //flag依次和byteRead的1-8位进行对比,并赋值
}
return byteRead;
}
完整demo:
#define PIN D2
//发送开始信号
void DHT11_Stat()
{
pinMode(PIN,OUTPUT);
digitalWrite(PIN,HIGH);
digitalWrite(PIN,LOW);
delay(20);
digitalWrite(PIN,HIGH);
delayMicroseconds(50);
if(digitalRead(PIN) == LOW){
while(digitalRead(PIN) == LOW);
while(digitalRead(PIN) == HIGH);
Serial.println("yes"); //检测到响应信号
}else{
Serial.println("no"); //未检测到响应信号(模块损坏/未连接)
}
}
//读取数据
uint8_t DHT11_readByte()
{
uint8_t i,flag,byteRead=0;
for(i=0;i<8;i++){
while(digitalRead(PIN) == LOW);
delayMicroseconds(35);
if(digitalRead(PIN) == HIGH){
flag = 1; //位数据读到1
while(digitalRead(PIN) == HIGH);
}else{
flag = 0; //位数据读到0
}
byteRead <<= 1; //每循环一次byteRead移动1位
byteRead |= flag; //flag依次和byteRead的1-8位进行对比,并赋值
}
return byteRead;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
uint8_t data[5];
DHT11_Stat();
for(int i=0;i<4;i++){
data[i] = DHT11_readByte(); //将温度及湿度的数据放到data上
}
Serial.print("HUMI:");
Serial.println(data[0]); //将温度的整数部分传到串口
Serial.print("TEMP:");
Serial.println(data[2]); //将湿度的整数部分传到串口
delay(2000);
}