ESP32 Arduino DHT11温湿度

一、接线

VCC接3.3V

DATA 接任意可配置输入输出的引脚(下文以P18为例)

二、流程

1、起始信号

配置为输出引脚,保持18ms低电平后拉高,再配置为输入引脚

2、 读取40bits数据

保持低电平50us后保持高电平。1位的高低由高电平保持时长决定(0则保持27us左右,1则保持70us左右)。

高位先接收。

数据接收结束,DHT11释放数据线,由上拉电阻保持高电平。

3、 校验和

只需将前4byte加起来

“8bit 湿度整数数据 + 8bit 湿度小数数据+8bit 温度整数数据 + 8bit 温度小数数据”8bit 校验位等于所 得结果的末 8 位。

4、 结果

由于DHT11温度测量范围在-20~+60℃,湿度为5~95%RH。需要判断温度为负的情况。

三、代码

#include <Arduino.h>

uint16_t time_outs;//时间计数存储器
unsigned char DHT11_buff[5];//5字节buff

uint8_t timesss[100];//每一状态值保持时长,用于测试
uint8_t timeindex;//时长数组的索引,用于测试

float Temperature, Humi;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(2000);//通电延迟,手册要求通电1S后才初始化完成
}

void delay_us(int uss)
{
    delayMicroseconds(uss);//可直接用于下面代码
}

//holdpin需要检测的pin值
//waitstate 等该状态变化至另一状态
//timeouts 微秒次数,超过该次数则故障 返回0,否则返回等待时长
//timeout_code如果超时,打印的故障码
int wait_pin(int holdpin, int waitstate, uint16_t timeouts, int timeout_code)
{
  time_outs = 0;
  while(digitalRead(holdpin)==waitstate)//直到状态改变
  {
    time_outs++;
    if(time_outs>timeouts)//超过timeouts了
    {
      Serial.printf("timeout %d\r\n",timeout_code);//打印故障码
      return 0;//时间不能为0,以0为错误码返回
    }
    delay_us(10);//也可以写成1,请和timeouts配合使用。
  }
  timesss[timeindex++] = time_outs;//保存保持时长
  return time_outs;
}

//读取一个byte
uint8_t get_dht11_byte()
{
  uint8_t buf8=0x00;
  uint8_t times_us;
  for(uint8_t i=0;i<8;i++)
  {
    buf8<<=1;
    times_us = wait_pin(18,0,6,-5);//50us,timeouts设为6,即不能超过60us
    if(times_us == 0)
      return 0xff;//byte不存在0xff的情况,作为错误码返回
    times_us = wait_pin(18,1,10,-6);//70us,等高电平,不能超过100us
    if(times_us == 0)
      return 0xff;
    if(times_us<4)
      buf8+=0;
    else
      buf8+=1;
  }
  return buf8;
}

//测量的完整流程
void dht_()
{
  uint8_t get_buff;//字节buff
  uint8_t isNegative;
  uint8_t checksum = 0;
  
  //起始信号
  pinMode(18,OUTPUT);
  digitalWrite(18,HIGH);
  digitalWrite(18,LOW);
  delay(19);//19ms低
  digitalWrite(18,HIGH);//上升沿

  pinMode(18,INPUT);//输入,悬浮(电路已有上拉电阻)
  delay_us(30);//设太长会超过低电平时间

  if(digitalRead(18))//判断有没有被DHT11拉低
  {
    if(wait_pin(18,1,10,400) == 0)//等DHT11响应
    {
      Serial.printf("err 1\r\n");//线路不对
      return;//超时退出
    }
  }
  //起始信号 -_____----_ 80+80
  if(wait_pin(18,0,20,-1) == 0)//拉低是否过长,80us
  {
    Serial.printf("err 2\r\n");//超时
    return;//超时退出
  }
  if(digitalRead(18))
  {
    if(wait_pin(18,1,11,-2) == 0)//拉高是否过长,80us
    {
      Serial.printf("err 3\r\n");
      return;//超时退出
    }
  
    //开始发送数据 1: ___---- 50+70 ; 0: ___-- 50+27
    
    for(uint8_t i=0;i<5;i++)//5字节
    {
      get_buff = get_dht11_byte();
      if(get_buff!=0xff)
        DHT11_buff[i] = get_buff;
      checksum +=get_buff;
    }
  
    Serial.printf("bytes:%d,%d,%d,%d,%d\n",DHT11_buff[0],DHT11_buff[1],
    DHT11_buff[2],DHT11_buff[3],DHT11_buff[4]);
  } 

  if(checksum == DHT11_buff[4])
  {
    isNegative = (( DHT11_buff[3] & 0x80 ) >> 7) ;//温度低字节的最高位为1时温度为负
    if ( 1 == iIsNegative )
    {
      Temperature = - ( (float)DHT11_buff[2] + ( (float)(DHT11_buff[3] & 0x7F)*0.1) );
    }
    else
    {
      Temperature =  (float)DHT11_buff[2] + (float)DHT11_buff[3]*0.1;
    }

    Humi = DHT11_buff[0];
   }
}

void loop() {
  // put your main code here, to run repeatedly:

  timeindex =0;
  dht_();

//打印各时段的时间
  for(uint8_t i=0;i<timeindex;i++)
    Serial.printf("%d :%d ,",i,timesss[i]);

  delay(1000);
}

代码未涉及中断、定时器,请放心食用。

四、 实验结果

 温度变化比较缓慢,湿度变化比较灵敏。

  • 3
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值