[APM32E0] 【APM32E030R Micro-EVB开发板评测】读取DHT11

[复制链接]
 楼主| 51xlf 发表于 2025-7-23 13:40 | 显示全部楼层 |阅读模式
DHT11是一款集温度和湿度测量于一体的数字传感器,采用单总线通信协议,具有体积小、功耗低、性价比高等特点‌。以下是其主要特性:
80fef5fded6c4c8921bf5e83bd9c723e.png

DHT11模块
微信截图_20250723133247.png
DHT11的连接方式
企业微信截图_20250723133427.png

这里我们使用的时PB1引脚。
微信截图_20250723133713.png

这里使用的是定时器3实现的定时功能
  1.    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
  2.        
  3.         TMR_TimeBase_T baseConfig;
  4.           baseConfig.div = 72-1;
  5.     baseConfig.period = 0xFFFF;
  6.     baseConfig.clockDivision = TMR_CKD_DIV1;
  7.     baseConfig.counterMode = TMR_COUNTER_MODE_UP;
  8.     TMR_ConfigTimeBase(TMR3, &baseConfig);
  9.     TMR_EnableAUTOReload(TMR3);
  10.                 TMR_Enable(TMR3);
1us定时的实现
  1. TMR3->CNT=0;
  2.         TMR_Enable(TMR3);
  3.         while(TMR3->CNT < nus);//计数频率6MHz,6次即为1us
  4.         TMR_Disable(TMR3);
DHT11的读写代码
dht11.c
  1. #include "dht11.h"
  2. #include "delay.h"
  3. void Delay_us(uint16_t time)
  4. {   
  5. delay_us(time);
  6. }

  7. void Delay_ms(uint16_t time)
  8. {   
  9.   delay_ms(time);
  10. }

  11. void DHT11_IO_OUT (void){ //温湿度模块输出函数
  12.     GPIO_Config_T  configStruct;
  13.     configStruct.pin = DHT11_IO; //选择端口号(0~15或all)                        
  14.     configStruct.mode = GPIO_MODE_OUT; //推挽输出      
  15.     configStruct.speed = GPIO_SPEED_50MHz; //设置IO接口速度(2/10/50MHz)   
  16.     GPIO_Config(DHT11_PORT, &configStruct);
  17. }

  18. void DHT11_IO_IN (void){ //温湿度模块输入函数       
  19.           GPIO_Config_T  configStruct;
  20.     configStruct.pin = DHT11_IO; //选择端口号(0~15或all)                        
  21.     configStruct.mode = GPIO_MODE_IN; //浮空输入   
  22.           configStruct.speed = GPIO_SPEED_50MHz; //设置IO接口速度(2/10/50MHz)   
  23.     GPIO_Config(DHT11_PORT, &configStruct);
  24. }

  25. void DHT11_RST (void){                                                 //DHT11端口复位,发出起始信号(IO发送)
  26.         DHT11_IO_OUT();                                                        //端口为输出
  27.         DHT11_DQ_OUT_0;         //使总线为低电平
  28.         Delay_ms(20);                                                         //拉低至少18ms                                               
  29.         DHT11_DQ_OUT_1;                 //使总线为高电平                                                       
  30.         Delay_us(30);                                                         //主机拉高20~40us
  31. }

  32. uint8_t DHT11_Check(void){         //等待DHT11回应,返回1:未检测到DHT11,返回0:成功(IO接收)          
  33.     uint8_t retry=0;                        //定义临时变量
  34.     DHT11_IO_IN();                //IO到输入状态         
  35. //GPIO端口输入时,配置为上拉输入或者浮空输入,因为外接上拉电阻,所以默认为高电平
  36. //有负信号输入,GPIO端口为1,当GPIO端口为1且retry小于100,retry自加,否则跳出循环执行下一步
  37.         while ((DHT11_DQ_IN == 1) && retry<100)        //DHT11会拉低40~80us
  38.         {
  39.                 retry++;
  40.         Delay_us(1);
  41.     }
  42.     if(retry>=100)return 1;        
  43.         else retry=0;
  44. //DHT11发来高电平信号,GPIO端口为0,当GPIO端口为0且retry小于100,retry自加,否则跳出循环执行下一步
  45.     while ((DHT11_DQ_IN == 0) && retry<100)  //DHT11拉低后会再次拉高40~80us
  46.         {  
  47.         retry++;
  48.         Delay_us(1);
  49.     }
  50.     if(retry>=100)return 1;            
  51.     return 0;
  52. }

  53. uint8_t DHT11_Init (void){        //DHT11初始化
  54.         RCM_EnableAPB2PeriphClock(DHT11_RCC);        //开始DHT11的时钟
  55.         DHT11_RST();                                                                //DHT11端口复位,发出起始信号
  56.         return DHT11_Check();                                                 //等待DHT11回应
  57. }

  58. //从DHT11读取一个位
  59. //返回值:1/0
  60. uint8_t DHT11_Read_Bit(void)
  61. {
  62.     uint8_t retry = 0;
  63.     while((DHT11_DQ_IN == 1) && retry < 100) //等待变为低电平
  64.     {
  65.         retry++;
  66.         Delay_us(1);
  67.     }
  68.     retry = 0;
  69.     while((DHT11_DQ_IN == 0) && retry < 100) //等待变高电平
  70.     {
  71.         retry++;
  72.         Delay_us(1);
  73.     }
  74.     Delay_us(40);//等待40us
  75.     if(GPIO_ReadInputBit(DHT11_PORT,DHT11_IO) == 1)       //用于判断高低电平,即数据1或0
  76.         return 1;
  77.     else
  78.         return 0;
  79. }

  80. //从DHT11读取一个字节
  81. //返回值:读到的数据
  82. uint8_t DHT11_Read_Byte(void)
  83. {
  84.     uint8_t i, dat;
  85.     dat = 0;
  86.     for (i = 0; i < 8; i++)
  87.     {
  88.         dat <<= 1;                                        //左移运算符,dat左移1位
  89.         dat |= DHT11_Read_Bit();        //"|"表示按位或等于
  90.     }
  91.     return dat;
  92. }

  93. //从DHT11读取一次数据
  94. //temp:温度值(范围:0~50°)
  95. //humi:湿度值(范围:20%~90%)
  96. //返回值:0,正常;1,读取失败
  97. uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi)
  98. {
  99.     uint8_t buf[5];
  100.     uint8_t i;
  101.     DHT11_RST();                                                //DHT11端口复位,发出起始信号
  102.     if(DHT11_Check() == 0)                                //等待DHT11回应,0为成功回应
  103.     {
  104.         for(i = 0; i < 5; i++)                         //读取40位数据
  105.         {
  106.             buf[i] = DHT11_Read_Byte();        //读出数据
  107.         }
  108.         if((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])        //数据校验
  109.         {
  110.             *humi = buf[0];                                //将湿度值放入指针humi
  111.             *temp = buf[2];                                //将温度值放入指针temp
  112.         }
  113.     }
  114.     else return 1;
  115.     return 0;
  116. }


dht11.h
  1. #ifndef __DHT11_H
  2. #define __DHT11_H
  3. #include "APM32E030_gpio.h"
  4. #include "APM32E030_rcm.h"

  5. #define DHT11_RCC              RCM_AHB_PERIPH_GPIOB                //开启引脚RCC,根据具体情况修改
  6. #define DHT11_PORT                         GPIOB                                                                //定义端口,根据具体情况修改
  7. #define DHT11_IO                                 GPIO_PIN_1                                        //定义IO口,根据具体情况修改

  8. //设置驱动IO端口
  9. #define DHT11_DQ_OUT_1 GPIO_SetBit(DHT11_PORT, DHT11_IO )
  10. #define DHT11_DQ_OUT_0 GPIO_ClearBit(DHT11_PORT, DHT11_IO )
  11. #define DHT11_DQ_IN GPIO_ReadInputBit(DHT11_PORT,DHT11_IO)
  12. void DHT11_IO_OUT (void);                                                                //设置IO口为输出模式
  13. void DHT11_IO_IN (void);                                                                //设置IO口为输入模式
  14. void DHT11_RST (void);                                                                        //复位DHT11

  15. uint8_t DHT11_Check (void);                                                                        //检查DHT11是否正常
  16. uint8_t DHT11_Read_Bit (void);                                                         //读取一位数据
  17. uint8_t DHT11_Read_Byte (void);                                                        //读取一个字节
  18. uint8_t DHT11_Init (void);                                                                                //DHT11初始化
  19. uint8_t DHT11_Read_Data (uint8_t *temp, uint8_t *humi);                 // DHT11读取数据

  20. #endif


main函数
  1. DHT11_Read_Data(&temperature,&humidity);        //读取温湿度值
  2.             sprintf(s_temp,"温度:%02d'C     ",temperature );
  3.             OLED_ShowStringCN(0,16,(unsigned char*)s_temp,1);// 显示温度
  4.                              sprintf(s_temp,"湿度:%02d%%    ",humidity  );
  5.             OLED_ShowStringCN(0,32,(unsigned char*)s_temp,1);// 显示湿度
  6.       OLED_Refresh();
最终实现的效果
微信截图_20250723133722.png

ShadowDance 发表于 2025-7-23 14:44 | 显示全部楼层
这个单总线通讯,是不是可以考虑使用SPI的通讯方式啊
抒情黎明 发表于 2025-7-30 17:33 | 显示全部楼层
纯延时处理的话,如果遇到中断,数据传输的稳定性还能保证吗?
魔法森林精灵 发表于 2025-7-31 08:08 | 显示全部楼层
这个评测很详细,特别是DHT11的连接和代码实现部分,对于初学者来说很有帮助。
幻想收藏家 发表于 2025-8-3 18:20 | 显示全部楼层
这个评测很详细,APM32E030R Micro-EVB开发板配合DHT11传感器的实现效果如何?
旧时光放映机 发表于 2025-8-6 12:12 | 显示全部楼层
看起来你已经成功地将DHT11传感器集成到APM32E030R Micro-EVB开发板上了。你的代码和截图提供了详细的步骤和配置,这对于其他开发者来说非常有参考价值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

547

主题

9919

帖子

24

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