Ai-M61-32SU DHT11温湿度传感器

[复制链接]
查看775 | 回复13 | 2024-5-19 18:08:17 | 显示全部楼层 |阅读模式
本帖最后由 lovzx 于 2024-5-20 13:58 编辑

DHT11温湿度传感器
运行效果
运行效果.png
实物图
DHT11.png DHT11模块.png


如图所示一般有3线、4线两种,
分别有

  • VDD(3.3~5.5V)
  • DATA串行线
  • NC
  • GND


测量范围


1. 湿度
湿度参数.png


2. 温度
温度.png


连接方式

1. VDD与M61-32模块的3v或5v连接
2. GND与M61-32模块的GND相连
3. 将DATA与M61-32模块的GPIO相连


通信/数据


DHT11采用的是单线串行通信协议,一次传输40bit,高位先出

数据格式


8bit湿度整数+8bit湿度小数(湿度小数部分为0)+8bit温度整数+8bit温度小数+8bit校验位

数据示例

00110101 00000000 00011000 00000100 01010001

数据解析:

湿度数据: 00110101(整数)=35H=53%RH
                  00000000(小数)=0H=0
最终读数: 53.0%

温度数据:00011000(整数)=18H=24℃
                 00000100(小数)=4H=4℃

最终读数:24+0.4=24.4℃

数据校验: 8bit温度整数+8bit温度小数+8bit湿度整数+8bit湿度小数=8bit校验位

通信协议

DHT采用单线串行通信协议,DHT作为从机使用,连接到主机后由主机发送信号控制DHT开始工作

通信时序图
时序图.png


主机拉低电平发送开始信号,然后再拉高电平,结束开始信号,后面就由DHT设备回应,然后发送数据了

协议分为三个阶段

  • 主机发送起始信号
  • 设备回应
  • 设备发送数据


并且要严格按照先后顺序,每个信号都有规定的时间范围

信号特性

信号特性.png


开始信号

  • 先将DATA信号拉高60us
  • 拉低20ms发送开始信号
  • 拉高13us开始信号结束


开始信号.png


DHT响应

  • DHT拉低83us响应收到开始数据
  • DHT拉高87us结束响应准备发送数据


响应信号.png


传输数据

  • 拉低54us开始发送数据
  • 拉高电平23us~27us表示数据0,68us~74us表示数据1


数据协议.png


代码实现

dht11.h代码

  1. #ifndef __DHT11_H
  2. #define __DHT11_H

  3. #include <stdint.h>
  4. #include "bflb_gpio.h"


  5. typedef enum {
  6.     DHT_CODE_SUCCEED = 0,
  7.     DHT_CODE_NOACK,
  8.     DHT_CODE_DATA_ERR,
  9. }DHT_CODE;

  10. typedef enum {
  11.     DHT_STATUS_INIT = 0,
  12.     DHT_STATUS_READY,
  13.     DHT_STATUS_READING,

  14. }DHT_STATUS;

  15. typedef struct DHT11 {
  16.     uint8_t pin;
  17.     DHT_STATUS status;
  18. }DHT11_t;

  19. #ifdef cplusplus

  20. extern "C" {
  21. #endif

  22.     /**
  23.      * @brief dht初始化
  24.      * @param  gpio
  25.      * @param  dev
  26.      * @param  pin 设备连接到的pin
  27.      */
  28.     void dht_init(struct bflb_device_s* gpio, DHT11_t* dev, uint8_t pin);
  29.     /**
  30.      * @brief 读取温湿度数据
  31.      * @param  gpio
  32.      * @param  dev
  33.      * @param  temp   温度*10
  34.      * @param  humidity  湿度*10
  35.      * @return DHT_CODE 状态码
  36.      */
  37.     DHT_CODE dht_read_data(struct bflb_device_s* gpio, DHT11_t* dev, int16_t* temp, uint16_t* humidity);

  38. #ifdef cplusplus
  39. }
  40. #endif
  41. #endif
复制代码



dht11.h中定义了dht_init初始化函数和dht_read_data读取函数


dht11.c文件

  1. #include "dht11.h"
  2. #include "bflb_gpio.h"
  3. #include "bflb_mtimer.h"
  4. #define CONFIG_LOG_NCOLOR 1
  5. #include "log.h"


  6. #define DHT_read_set(gpio,dev)  \
  7.     do                          \
  8.     {                           \
  9.         bflb_gpio_init(gpio,    \
  10.         dev->pin,               \
  11.         GPIO_INPUT|GPIO_PULLUP|GPIO_SMT_EN|GPIO_DRV_0); \
  12.     }while (0)

  13. #define DHT_write_set(gpio,dev)     \
  14.     do                              \
  15.     {                               \
  16.         bflb_gpio_init(gpio,        \
  17.             dev->pin,               \
  18.             GPIO_OUTPUT|GPIO_PULLUP|GPIO_SMT_EN|GPIO_DRV_0);\
  19.     } while (0);


  20. void dht_init(struct bflb_device_s* gpio, DHT11_t* dev, uint8_t pin) {

  21.     dev->status = DHT_STATUS_INIT;
  22.     dev->pin = pin;
  23.     DHT_write_set(gpio, dev);
  24.     bflb_gpio_set(gpio, dev->pin);
  25.     //等待1s越过不稳定状态
  26.     bflb_mtimer_delay_ms(1000);
  27.     dev->status = DHT_STATUS_READY;
  28. }

  29. uint8_t dht_check(struct bflb_device_s* gpio, DHT11_t* dev) {
  30.     DHT_read_set(gpio, dev);
  31.     uint8_t retry = 0;
  32.     //dht会拉低电平80us
  33.     while (!bflb_gpio_read(gpio, dev->pin) && retry < 100) {
  34.         retry++;
  35.         bflb_mtimer_delay_us(1);
  36.     }
  37.     if (retry >= 100) {
  38.         return 0;
  39.     }
  40.     retry = 0;
  41.     //再次拉高80us
  42.     while (bflb_gpio_read(gpio, dev->pin) && retry < 100) {
  43.         retry++;
  44.         bflb_mtimer_delay_us(1);
  45.     }
  46.     if (retry >= 100) {
  47.         return 0;
  48.     }
  49.     else {
  50.         return 1;
  51.     }
  52. }

  53. static uint8_t dht_read_bit(struct bflb_device_s* gpio, DHT11_t* dev) {
  54.     uint8_t retry = 0;
  55.     //54us低电平
  56.     while (!bflb_gpio_read(gpio, dev->pin) && retry < 70) {
  57.         retry++;
  58.         bflb_mtimer_delay_us(1);
  59.     }
  60.     retry = 0;
  61.     //高电平23~27us是0,高电平68~71us是1
  62.     //延迟30us
  63.     bflb_mtimer_delay_us(35);
  64.     uint8_t ret = bflb_gpio_read(gpio, dev->pin);
  65.     //等待高电平结束
  66.     if (ret) {
  67.         while (bflb_gpio_read(gpio, dev->pin) && retry < 50) {
  68.             retry++;
  69.             bflb_mtimer_delay_us(1);
  70.         }
  71.     }

  72.     return ret;
  73. }

  74. static int8_t dht_read_byte(struct bflb_device_s* gpio, DHT11_t* dev) {
  75.     int8_t ret = 0;
  76.     for (int i = 0; i < 8; i++) {
  77.         ret <<= 1;
  78.         ret |= dht_read_bit(gpio, dev);
  79.     }
  80.     return ret;
  81. }
  82. DHT_CODE dht_read_data(struct bflb_device_s* gpio, DHT11_t* dev, int16_t* temp, uint16_t* humidity) {
  83.     //检查dev状态
  84.     if (dev->status != DHT_STATUS_READY) {
  85.         return dev->status;
  86.     }

  87.     dev->status = DHT_STATUS_READING;
  88.     //空闲高电平
  89.     DHT_write_set(gpio, dev);
  90.     bflb_gpio_set(gpio, dev->pin);
  91.     bflb_mtimer_delay_us(60);

  92.     //拉低电平20ms上,发送开始信号
  93.     bflb_gpio_reset(gpio, dev->pin);
  94.     bflb_mtimer_delay_ms(20);

  95.     // //拉高电平延迟10 ~ 20us,结束开始信号
  96.     bflb_gpio_set(gpio, dev->pin);
  97.     bflb_mtimer_delay_us(13);

  98.     DHT_CODE ret = DHT_CODE_SUCCEED;
  99.     uint8_t buf[5] = { 0 };
  100.     //检测设备
  101.     if (dht_check(gpio, dev)) {
  102.         for (int i = 0;i < 5;i++) {
  103.             buf[i] = dht_read_byte(gpio, dev);
  104.         }
  105.         uint16_t sum = buf[0] + buf[1] + buf[2] + buf[3];

  106.         if (sum == buf[4]) {
  107.             *humidity = buf[0] * 10 + buf[1];
  108.             //温度小数数据第8位为1代表负数,低7位代表实际数值
  109.             *temp = buf[2] * 10 + (buf[3] & 0x7f);
  110.             if ((buf[3] & 0x80) == 0x80) {
  111.                 *temp = -*temp;
  112.             }
  113.         }
  114.         else {
  115.             LOG_E("%d,%d,%d,%d,sum: %d,buf[4]: %d\n", buf[0], buf[1], buf[2], buf[3], sum, buf[4]);
  116.             ret = DHT_CODE_DATA_ERR;
  117.         }
  118.     }
  119.     else {
  120.         ret = DHT_CODE_NOACK;
  121.         LOG_E("设备未回复\n");
  122.     }

  123.     dev->status = DHT_STATUS_READY;
  124.     return ret;
  125. }
复制代码



main.c


main.c中使用读取函数

  1. #include "dht11.h"
  2. #include "board.h"
  3. #define CONFIG_LOG_NCOLOR 1
  4. #include "log.h"
  5. #include "bflb_mtimer.h"

  6. int main()
  7. {
  8.     board_init();

  9.     printf("dht11 start\n");
  10.     DHT11_t dht;
  11.     struct bflb_device_s* gpio;
  12.     gpio = bflb_device_get_by_name("gpio");
  13.     dht_init(gpio, &dht, GPIO_PIN_10);
  14.     int ret = 0;
  15.     int16_t temp = 0;
  16.     uint16_t humidity = 0;
  17.    
  18.     while (1) {

  19.         ret = dht_read_data(gpio, &dht, &temp, &humidity);
  20.         if (ret == DHT_CODE_SUCCEED) {
  21.             LOG_I("温度:%.1fC°, 湿度:%.1f%%\n", temp / 10.0f, humidity / 10.0f);
  22.         }
  23.         else {
  24.             LOG_E("ret: %d\n", ret);
  25.         }

  26.         bflb_mtimer_delay_ms(2000);

  27.     }
  28.     return 0;
  29. }
复制代码



可能遇到的问题

1. 数据都是0
确保GPIO模式正确,DATA正确连接到代码所用到GPIO的PIN引脚

1. 数据都是1
这种情况是DHT没有收到开始信号,确保主机发送了开始信号
注意:开始信号发送低电平信号20ms,单位是ms不是us,通信过程中其他信号时间单位都是us

1. 解析出错
一共40个bit数据,高位先出,按照8bit湿度整数数据+8bit湿度小数部分+8bit温度整数部分+8bit温度小数部分+8bit校验位

注意:温度小数部分8bit数据,第8位为1表示负数为零下,为零表示正数,后7位才是真正的数据,第8位只表示正负值

例:温度整数部分为0000 0020,小数部分为:1000 0001
整数部分为2,小数部分为1,第8位为1,所以最终温度为-2.1℃
代码下载  https://gitee.com/jrobot_Q_Q/m61-32-u-dht11.git

回复

使用道具 举报

WT_0213 | 2024-5-19 20:12:45 | 显示全部楼层
回复

使用道具 举报

1084504793 | 2024-5-20 08:36:25 | 显示全部楼层
回复

使用道具 举报

爱笑 | 2024-5-20 08:52:49 | 显示全部楼层
不错不错!
用心做好保姆工作
回复

使用道具 举报

djy876 | 2024-5-20 09:43:39 | 显示全部楼层
这个适用DHT20吗
回复 支持 反对

使用道具 举报

1055173307 | 2024-5-20 11:15:03 | 显示全部楼层
学习
回复

使用道具 举报

lovzx | 2024-5-20 13:55:14 | 显示全部楼层

不可以的,dht20是I²C协议的,接线方式都不一样
回复 支持 反对

使用道具 举报

lovzx | 2024-5-20 13:58:43 | 显示全部楼层

像王哥学习
回复 支持 反对

使用道具 举报

lovzx | 2024-5-20 14:10:11 | 显示全部楼层
回复 支持 反对

使用道具 举报

lovzx | 2024-5-20 17:03:42 | 显示全部楼层

好想要那个板载天线的开发板啊,我的32SU不带天线
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则