[活动专区] 【AT-START-F423测评】5.单数据线通讯读取DHT11温湿度

[复制链接]
 楼主| yuyy1989 发表于 2023-10-27 19:28 | 显示全部楼层 |阅读模式
<
#申请原创# @21小跑堂  

DHT11是一种数字温湿度传感器,使用一根数据线进行数据传输,要求IO既能输出又能输入,使用开漏输出模式正好能满足要求
开漏模式下GPIO可以真正输出低电平,输出高电平需要借助上拉电阻,当需要作为输入时,只需要程序内输出高电平,之后外设就可以控制电平高低了
QQ截图20231027190315.png
在AT32 Work Bench中将PD8配置成开漏输出,DHT11已经内置了10K的上拉电阻,这里就不配置上拉了,默认输出高电平

QQ截图20231027182829.png
实现GPIO的操作,开漏模式下可以通过读输入读取真实的电平
  1. #define YUYY_GPIO_LEV_TYPE flag_status
  2. #define YUYY_GPIO_LEV1 SET
  3. #define YUYY_GPIO_LEV0 RESET
  4. void yuyy_gpio_setlev(YUYY_GPIO_DEV_t *gpio_dev,YUYY_GPIO_LEV_TYPE lev)
  5. {
  6.     gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,lev);
  7. }
  8. YUYY_GPIO_LEV_TYPE yuyy_gpio_readlev(YUYY_GPIO_DEV_t *gpio_dev)
  9. {
  10.      return gpio_input_data_bit_read(gpio_dev->gpio,gpio_dev->pin);
  11. }
  12. void yuyy_gpio_opod_out(YUYY_GPIO_DEV_t *gpio_dev)
  13. {
  14.    
  15. }
  16. void yuyy_gpio_opod_in(YUYY_GPIO_DEV_t *gpio_dev)
  17. {
  18.     gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,YUYY_GPIO_LEV1);
  19. }
参考手册实现DHT11的通讯
QQ截图20231027190025.png
  1. enum
  2. {
  3.     YUYY_DHT11_OK = 0,
  4.     YUYY_DHT11_ERROR_DATIOBUSY,
  5.     YUYY_DHT11_ERROR_NOACK,
  6.     YUYY_DHT11_ERROR_ACKBLOCK,
  7.     YUYY_DHT11_ERROR_READDATA,
  8.     YUYY_DHT11_ERROR_DATACHECK
  9. };
  10. typedef struct
  11. {
  12.     YUYY_GPIO_DEV_t dat;
  13. }YUYY_DHT11_DEV_t;
  14. uint8_t yuyy_dht11_readHT(YUYY_DHT11_DEV_t *dht11_dev,float *tem,float *hum)
  15. {
  16.     uint8_t retry = 0,i=0,j=0,check=0;
  17.     uint8_t buffer[5] = {0};
  18.     yuyy_gpio_opod_out(&(dht11_dev->dat)); //输出模式
  19.     yuyy_gpio_setlev(&(dht11_dev->dat),YUYY_GPIO_LEV0); //拉低
  20.     yuyy_dht11_delay_ms(20);
  21.     yuyy_gpio_opod_in(&(dht11_dev->dat)); //输入模式
  22.     retry = 0;
  23.     while  (yuyy_gpio_readlev(&(dht11_dev->dat)) == YUYY_GPIO_LEV0)
  24.     {
  25.         yuyy_dht11_delay_us(10);
  26.         retry += 1;
  27.         if(retry > 2)
  28.             return YUYY_DHT11_ERROR_DATIOBUSY;
  29.     }
  30.     while (yuyy_gpio_readlev(&(dht11_dev->dat)) == YUYY_GPIO_LEV1)
  31.     {
  32.         yuyy_dht11_delay_us(10);
  33.         retry += 1;
  34.         if(retry > 20)
  35.             return YUYY_DHT11_ERROR_NOACK;
  36.     }
  37.     retry = 0;
  38.     while  (yuyy_gpio_readlev(&(dht11_dev->dat)) == YUYY_GPIO_LEV0)
  39.     {
  40.         yuyy_dht11_delay_us(10);
  41.         retry += 1;
  42.         if(retry > 9)
  43.             return YUYY_DHT11_ERROR_ACKBLOCK;
  44.     }
  45.     retry = 0;
  46.     while (yuyy_gpio_readlev(&(dht11_dev->dat)) == YUYY_GPIO_LEV1)
  47.     {
  48.         yuyy_dht11_delay_us(10);
  49.         retry += 1;
  50.         if(retry > 10)
  51.             return YUYY_DHT11_ERROR_ACKBLOCK;
  52.     }
  53.     while(i<5)
  54.     {
  55.         j = 0;
  56.         while (j < 8)
  57.         {
  58.             buffer[i] <<= 1;
  59.             retry = 0;
  60.             while (yuyy_gpio_readlev(&(dht11_dev->dat)) == YUYY_GPIO_LEV0)
  61.             {
  62.                 yuyy_dht11_delay_us(10);
  63.                 retry += 1;
  64.                 if(retry > 6)
  65.                     return YUYY_DHT11_ERROR_READDATA;
  66.             }
  67.             retry = 0;
  68.             while (yuyy_gpio_readlev(&(dht11_dev->dat)) == YUYY_GPIO_LEV1)
  69.             {
  70.                 yuyy_dht11_delay_us(10);
  71.                 retry += 1;
  72.                 if(retry > 8)
  73.                     return YUYY_DHT11_ERROR_READDATA;
  74.             }
  75.             if(retry > 5)
  76.                 buffer[i] |= 0x01;
  77.             j += 1;
  78.         }
  79.         if(i<4)
  80.             check += buffer[i];
  81.         i += 1;
  82.     }
  83.     if(check != buffer[4])
  84.         return YUYY_DHT11_ERROR_DATACHECK;
  85.     *hum = buffer[0];
  86.     *tem = buffer[2];
  87.     if((buffer[3] & 0x7F) < 10)
  88.     {
  89.         *tem += (buffer[3] & 0x7F)/10.0;
  90.     }
  91.     if((buffer[3] & 0x80) > 0)
  92.         *tem = 0 - *tem;
  93.     return YUYY_DHT11_OK;
  94. }
使用printf打印温湿度
  1. YUYY_DHT11_DEV_t dht11_dev;
  2. void dht11_init()
  3. {
  4.     dht11_dev.dat.gpio = DHT11_DAT_GPIO_PORT;
  5.     dht11_dev.dat.pin = DHT11_DAT_PIN;
  6. }

  7. void dht11_readHT()
  8. {
  9.     float humi,temp;
  10.     uint8_t result = yuyy_dht11_readHT(&dht11_dev,&temp,&humi);
  11.     if(YUYY_DHT11_OK == result)
  12.     {
  13.         printf("DHT11 读取 温度:%.1f℃ 湿度:%.1f%%",temp,humi);
  14.     }
  15.     else
  16.     {
  17.         printf("DHT11 读取错误:%d",result);
  18.     }
  19. }
运行效果
QQ截图20231027185946.png
结合之前的LCD屏幕,可以做个简单地温湿度监测器
微信图片_20231027192253.jpg

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

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部