发帖
2 1 0

Ai-WB2 读取DHT11温湿度传感器

WildboarG
论坛元老

25

主题

165

回帖

3859

积分

论坛元老

积分
3859
Ai-WB2系列 35 2 前天 16:01
[i=s] 本帖最后由 WildboarG 于 2025-4-11 16:06 编辑 [/i]

WB2 读取DHT11温湿度传感器


说明


DHT11 既能检测温度又能检测湿度,不过 DHT11 的精度和测量范围都要低于 DS18B20,其温度测量范围为 0~50℃,误差在±2℃;湿度的测量范围为 20%~90%RH(Relative Humidity 相对湿度—指空气中水汽压与饱和水汽压的百分比),误差在±5%RH。

DHT11 电路很简单,只需要将 DATA 引脚连接单片机的一个 I/O 即可,不过该引脚需要上拉一个 5K 的电阻,DHT11 的供电电压为 3~5.5V。

数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,一共 5 字节(40bit)数据。

由于 DHT11 分辨率只能精确到个位,所以小数部分是数据全为 0。校验和为前 4 个字节数据相加,校验的目的是为了保证数据传输的准确性。

DHT11 只有在接收到开始信号后才触发一次温湿度采集,如果没有接收到主机发送复位信号,DHT11 不主动进行温湿度采集。当数据采集完毕且无开始信号后,DHT11 自动切换到低速模式。

注意:由于 DHT11 时序要求非常严格,所以在操作时序的时候,为了防止中断干扰总线时序,先关闭总中断,操作完毕后再打开总中断。( 一次通信大概4ms左右)

电路连接

图片1.png

通讯时序

代码


手把手敲

  • 新建一个工程 dht11
> wb2-cli create
> Create New Project:dht11
> successfuly
  • 进入路径下编写 main.c
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <bl_gpio.h>
#include <bl_timer.h>
#include <blog.h>
#include <dht11.h>

#define GPIO_DHT 4  //定义工作引脚

extern unsigned int rec_data[4];
int main(void) {

  // add your code here
  bl_gpio_enable_output(GPIO_DHT, 0, 0);
  printf("start DTH11\r\n");
  while (1) {
    DHT11_REC_Data();
    bl_timer_delay_us(1000 * 1000);
    printf("Temperature:%d°C Humidity:%d%% \r\n", rec_data[2], rec_data[0]);
  }
}
  • 编写 dht11.h
#ifndef __DHT11_H__
#define __DHT11_H__
#include "bl_timer.h"
#include <bl_gpio.h>

#define GPIO_DHT 4
#define dht11_high bl_gpio_output_set(GPIO_DHT, 1)
#define dht11_low bl_gpio_output_set(GPIO_DHT, 0)
#define Read_Data bl_gpio_input_get_value(GPIO_DHT)

void DHT11_GPIO_Init_OUT(void);
void DHT11_GPIO_Init_IN(void);
void DHT11_Start(void);
unsigned char DHT11_REC_Byte(void);
void DHT11_REC_Data(void);

#endif
  • 编写 dht11.c 驱动函数
#include "dht11.h"

// 数据存放
unsigned int rec_data[4];

// 做为输出
void DH11_GPIO_Init_OUT(void) { bl_gpio_enable_output(GPIO_DHT, 0, 0); }

// 做为输入
void DH11_GPIO_Init_IN(void) { bl_gpio_enable_input(GPIO_DHT, 0, 0); }

// 主机发送开始信号
void DHT11_Start(void) {
  DH11_GPIO_Init_OUT(); // 输出模式

  dht11_high; // 先拉高
  bl_timer_delay_us(30);

  dht11_low; // 拉低电平至少18us
  bl_timer_delay_us(20 * 1000);

  dht11_high; // 拉高电平20~40us
  bl_timer_delay_us(30);

  DH11_GPIO_Init_IN(); // 输入模式
}

// 获取一个字节
char DHT11_Rec_Byte(void) {
  unsigned char i = 0;
  unsigned char data = 0;

  for (i = 0; i < 8; i++) // 1个数据就是1个字节byte,1个字节byte有8位bit
  {
    while (Read_Data == 0)
      ;                    // 从1bit开始,低电平变高电平,等待低电平结束
    bl_timer_delay_us(30); // 延迟30us是为了区别数据0和数据1,0只有26~28us

    data <<= 1; // 左移

    if (Read_Data == 1) // 如果过了30us还是高电平的话就是数据1
    {
      data |= 1; // 数据+1
    }

    while (Read_Data == 1)
      ; // 高电平变低电平,等待高电平结束
  }
  return data;
}

// 获取数据

void DHT11_REC_Data(void) {
  unsigned int R_H = 0, R_L = 0, T_H = 0, T_L = 0;
  unsigned char RH = 0, RL = 0, TH = 0, TL = 0, CHECK = 0;

  DHT11_Start(); // 主机发送信号
  dht11_high;    // 拉高电平

  if (Read_Data == 0) // 判断DHT11是否响应
  {
    while (Read_Data == 0)
      ; // 低电平变高电平,等待低电平结束
    while (Read_Data == 1)
      ; // 高电平变低电平,等待高电平结束

    R_H = DHT11_Rec_Byte();
    R_L = DHT11_Rec_Byte();
    T_H = DHT11_Rec_Byte();
    T_L = DHT11_Rec_Byte();
    CHECK = DHT11_Rec_Byte(); // 接收5个数据

    dht11_low;             // 当最后一bit数据传送完毕后,DHT11拉低总线 50us
    bl_timer_delay_us(55); // 这里延时55us
    dht11_high;            // 随后总线由上拉电阻拉高进入空闲状态。

    if (R_H + R_L + T_H + T_L ==
        CHECK) // 和检验位对比,判断校验接收到的数据是否正确
    {
      RH = R_H;
      RL = R_L;
      TH = T_H;
      TL = T_L;
    }
  }
  rec_data[0] = RH;
  rec_data[1] = RL;
  rec_data[2] = TH;
  rec_data[3] = TL;
}
  • 完成然后编译
make -j32
  • 烧录
make flash

显示

打开串口助手看一下结果

图片.png

连接图

8ae6da52443cc68547d879fc2b5512df.jpg

用小玩意飞了两根线,效果还是很不错

链接


图三摘自lovzxAi-M61-32SU DHT11温湿度传感器

──── 1人觉得很赞 ────

使用道具 举报

那是桔梗吗。自己花的板子么。
前天 17:51
WT_0213 发表于 2025-4-11 17:49
那是桔梗吗。自己花的板子么。

是的,一个uhub彩色丝印
您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28389 个
  • 话题数: 40440 篇