参考——温湿度传感器DHT11驱动_STM32

打印 上一主题 下一主题

主题 955|帖子 955|积分 2865

装备stm32f407ZGT6
环境FreeRTOS        HAL

一、简介

        到网上找DHT11的驱动,但是都无法使用。原因是RTOS环境中,由于多线程,使用循环计数壅闭式的delay_us延时函数就没那么准,且差别装备中delay_us的计数值不一样。而DHT11对时序要求得又十分严酷,这就会导致读取数据异常,甚至无法读取。
  1. /**********************************************************************************************************
  2. 函数名称:us延时函数,最小延时为1us
  3. 输入参数:时间
  4. 输出参数:无
  5. **********************************************************************************************************/
  6. void delay_us(unsigned int time)
  7. {
  8.     unsigned short i = 0;
  9.     while (time--)
  10.     {
  11.         i = 8;
  12.         while (i--)
  13.             ;
  14.     }
  15. }
复制代码
        而且这个DHT11间隔若干秒一连读取一段时间后,会在某次读取第一个完整字节后就会莫名其妙卡住,不知道是不是硬件的标题。这个没有什么好办法解决,在读取的时间加个超时判断语句,超时就返回false        
        虽然考虑过使用其他方法到达更精准的微秒级延时,但还是想尝试一下用不那么精准的方法来完成。于是下面就简朴的使用计数值来模拟延时,不需要考虑延时多少微秒,只需要比较高电平持续时间的相对长短。

二、代码

1,大略分析


        时序很好分析。分为主机部分DHT部分。通讯的整个过程是主机先向DHT发送开始信号,假如DHT回应了(大多数情况都会回应,除非延时不准),那么就读取数据,读取竣事后再拉高(实测过程中,这个加不加都会间歇性卡住。这里没有加)


发送开始信号
  1. inline void DHT11_Rst()
  2. {
  3.     DHT11_OUT();
  4.     DHT11_Low();
  5.     osDelay(30);//根据时序图可知,需要至少拉低18ms。换成自己的延时函数,不需要太准
  6.     DHT11_High();
  7.     std_delay_25us();//20-40us,不需要太准,它与它上面的那行代码也可以不加
  8. }
复制代码
检测DHT相应
  1. inline void DHT11_Check()
  2. {
  3.     DHT11_IN();
  4.     while (DHT11_Read())
  5.         ;
  6.     while (!DHT11_Read())
  7.         ;
  8. }
复制代码





读取一位数据

        当DHT输出相应后会拉高一段时间,然后才会拉低,进入一个50us的低电平间隙,等再次拉高时就是读取数据的时间
此后在读取上一位数据竣事后,都会拉低50us,然后再次拉高来读取数据
        根据上面两种情况,所以统一先等待拉低,以便进入50us的低电平间隙。然后再等待拉高,以便读取数据,最后再等待拉低,在这两个操作中用计数值来记录时间长短。
0:26-28us
1:70us
  1.             while (DHT11_Read()) {} // 等待低电平
  2.             while (!DHT11_Read()) {}// 等待变高电平
  3.             // 开始读数据
  4.             uint16_t time_count = 0;
  5.             for (; DHT11_Read() && time_count < DHT11_MAX_DELAY_COUNT; ++time_count) {}
  6.             if (time_count >= DHT11_MAX_DELAY_COUNT)
  7.             {
  8.                 return false;
  9.             }
  10.             timeBuf[timeBufIndex++] = time_count >> 4;// 存储计数值,由于事先已经知道一个为
复制代码
        上面这个读取一位数据是可以简化的,因为按照下面读取的规则,其实是不需要每次都要在开头等待低电平。但是检测DHT输出相应后需要等待低电平 
        简化后是这样的,读取一位数据不需要考虑许多,只需要等待变为高电平就行了。但是检测DHT11相应考虑的就比较多了,需要再次等待低电平。
  1. inline void DHT11_Check()
  2. {
  3.     DHT11_IN();
  4.     while (DHT11_Read())    //等待低电平
  5.         ;
  6.     while (!DHT11_Read())   //等待高电平
  7.         ;//也可以在这里计数,用于测量80us所需的计数值,从而测算出20us、40us等对应的计数值
  8.     while (DHT11_Read()) {} // 等待低电平
  9. }
复制代码
  1.             while (!DHT11_Read()) {}// 等待变高电平
  2.             // 开始读数据
  3.             uint16_t time_count = 0;
  4.             for (; DHT11_Read() && time_count < DHT11_MAX_DELAY_COUNT; ++time_count) {}
  5.             if (time_count >= DHT11_MAX_DELAY_COUNT)
  6.             {
  7.                 return false;
  8.             }
  9.             timeBuf[timeBufIndex++] = time_count >> 4;// 存储计数值,由于事先已经知道一个为
复制代码

读取一个字节
        这个只要一个for循环即可,循环8次。这里是未简化的版本。读取5个字节就是再套个for循环,循环5次即可
  1.         //读取一字节        for (uint8_t j = 0; j < 8; j++)        {            while (DHT11_Read()) {} // 等待低电平
  2.             while (!DHT11_Read()) {}// 等待变高电平
  3.             // 开始读数据
  4.             uint16_t time_count = 0;
  5.             for (; DHT11_Read() && time_count < DHT11_MAX_DELAY_COUNT; ++time_count) {}
  6.             if (time_count >= DHT11_MAX_DELAY_COUNT)
  7.             {
  8.                 return false;
  9.             }
  10.             timeBuf[timeBufIndex++] = time_count >> 4;// 存储计数值,由于事先已经知道一个为875,一个为275左右,所以除以16        }
复制代码

数据处理
使用中位数来区分高电平持续的时间是长是短,以便判断是1还是0。正常情况下,这个持续时间差别很明显。
  1. //找出最大计数值和最小计数值,用以判断是1还是0
  2.     uint16_t timeMax = 0;
  3.     uint16_t timeMin = 0xFFFF;
  4.     for (unsigned short i: timeBuf)
  5.     {
  6.         if (i > timeMax) timeMax = i;
  7.         if (i < timeMin) timeMin = i;
  8.     }
  9.     uint16_t timeMed = (timeMax + timeMin) >> 1;// 取中位数,以区分时间长短
  10. // 转为二进制数据,进而转为字节数据
  11.     for (uint8_t i = 0; i < 5; ++i)
  12.     {
  13.         uint8_t data = 0;
  14.         for (uint8_t j = 0; j < 8; j++)
  15.         {
  16.             data <<= 1;
  17.             data |= (timeBuf[i * 8 + j] > timeMed);
  18.         }
  19.         buf[i] = data;// 存储数据
  20.     }
复制代码


2,完整代码

需要注意的是,下面代码使用的是C++,假如你使用的是C,那么用相应功能的代码替换掉即可。bool范例需要包罗stdbool头文件
DHT11.h
        头文件里未被注释的接口,决定了哪些函数需要重点关注
  1. #ifndef DHT11_H
  2. #define DHT11_H
  3. void DHT11_Init();
  4. //bool DHT11_Read_Data(float &temp,float &humi);
  5. bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi);//自定义的快速读取函数
  6. #endif//DHT11_H
复制代码



DHT11.cpp
        内里的这个std_delay_us是用于调试中用的,在void DHT11_Rst()函数里,你把延时换成你自带的即可,这个不需要多精准。
        下面的函数是与时序图直接对应的,一连读取温度时,最好间隔1s以上。
        后面还有一个版本
  1. #include "DHT11.h"#include "cmsis_os2.h"#include "stm32f4xx_hal.h"#define DHT11_Pin GPIO_PIN_6#define DHT11_Pin_Location 6    //第几个引脚就写几#define DHT11_GPIO_Port GPIOE#define DHT11_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()#define DHT11_MAX_DELAY_COUNT 7000//防止卡死#define DHT11_Read() (DHT11_GPIO_Port->IDR & DHT11_Pin) /*HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin)*/#define DHT11_High() DHT11_GPIO_Port->ODR |= (0x01 << DHT11_Pin_Location)#define DHT11_Low() DHT11_GPIO_Port->ODR &= ~(0x01 << DHT11_Pin_Location) /*HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET)*/#define DHT11_IN()                                                  \    {                                                               \        DHT11_GPIO_Port->MODER &= ~(3 << (2 * DHT11_Pin_Location)); \        DHT11_GPIO_Port->MODER |= 0 << 2 * DHT11_Pin_Location;      \    }#define DHT11_OUT()                                                 \    {                                                               \        DHT11_GPIO_Port->MODER &= ~(3 << (2 * DHT11_Pin_Location)); \        DHT11_GPIO_Port->MODER |= 1 << 2 * DHT11_Pin_Location;      \    }//static uint16_t std_delay_80us = 875;//事先测试过//static uint16_t std_delay_50us = 566;/**动态计算延时,以确保任何情况下都可以得到较为精确的延时*///根据80us的那段时序,通过计数值得到80us需要的计数值,然后以此测算差别us的延时,在Check函数里,这里省略了//void std_delay_us(uint8_t us)//{//    //   uint16_t count = std_delay_80us * us / 80;//测试得到的,但乘法会有很大的延时,所以只能作为计算公式//    uint16_t count = 11 * us;//    for (uint16_t i = 0; i < count; ++i)//        ;//}//这个延时函数可以换成本身的延时,因为装备差别、代码环境差别,延时的计数就差别//可以通过上面那个方法来计算,测算的是Check函数里的80s延时inline void std_delay_25us(){    for (uint16_t i = 0; i < 20; ++i)//单个使命时为273        ;}/**函数*/inline void DHT11_Rst();void DHT11_Init(){    GPIO_InitTypeDef GPIO_InitStruct = {0};    DHT11_GPIO_CLK_ENABLE();    GPIO_InitStruct.Pin = DHT11_Pin;    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;    GPIO_InitStruct.Pull = GPIO_PULLUP;    //    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;    HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);    DHT11_High();}inline void DHT11_Rst(){    DHT11_OUT();    DHT11_Low();    osDelay(30);//根据时序图可知,需要至少拉低18ms    DHT11_High();    std_delay_25us();//20-40us}inline void DHT11_Check()
  2. {
  3.     DHT11_IN();
  4.     while (DHT11_Read())
  5.         ;
  6.     while (!DHT11_Read())
  7.         ;
  8. }// 全局变量static uint8_t timeBuf[40];// 存储计数值static uint8_t timeBufIndex = 0;bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi){    static uint8_t buf[5];    DHT11_Rst();  // 设置输出模式    DHT11_Check();// 设置输入模式    timeBufIndex = 0;          // 重置计数值索引    for (unsigned char &i: buf)// 读取40位数据    {        //        DHT11_Read_Byte_Fast_Pro();        //读取一字节        for (uint8_t j = 0; j < 8; j++)        {            while (DHT11_Read()) {} // 等待低电平
  9.             while (!DHT11_Read()) {}// 等待变高电平
  10.             // 开始读数据
  11.             uint16_t time_count = 0;
  12.             for (; DHT11_Read() && time_count < DHT11_MAX_DELAY_COUNT; ++time_count) {}
  13.             if (time_count >= DHT11_MAX_DELAY_COUNT)
  14.             {
  15.                 return false;
  16.             }
  17.             timeBuf[timeBufIndex++] = time_count >> 4;// 存储计数值,由于事先已经知道一个为875,一个为275左右,所以除以16        }    }//找出最大计数值和最小计数值,用以判断是1还是0    uint16_t timeMax = 0;    uint16_t timeMin = 0xFFFF;    for (unsigned short i: timeBuf)    {        if (i > timeMax) timeMax = i;        if (i < timeMin) timeMin = i;    }    uint16_t timeMed = (timeMax + timeMin) >> 1;// 取中位数    for (uint8_t i = 0; i < 5; ++i)    {        uint8_t data = 0;        for (uint8_t j = 0; j < 8; j++)        {            data <<= 1;            data |= (timeBuf[i * 8 + j] > timeMed);        }        buf[i] = data;// 存储数据    }    //校验数据    if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])    {        humi = (buf[0] * 10 + buf[1]) / 10.0f;        temp = (buf[2] * 10 + buf[3]) / 10.0f;        return true;    }    else    {        return false;    }}
复制代码
内里有多个版本,第0个是特化版本,其下愈为通用。只有第1个版本(没有注释的)加了防卡死的判断语句
  1. #include "DHT11.h"
  2. #include "cmsis_os2.h"
  3. #include "stm32f4xx_hal.h"
  4. #define DHT11_Pin GPIO_PIN_6
  5. #define DHT11_Pin_Location 6
  6. #define DHT11_GPIO_Port GPIOE
  7. #define DHT11_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()
  8. #define DHT11_MAX_DELAY_COUNT 4000//防止卡死
  9. #define USE_YZHX 1                //优化等级,分为0,1,2,3
  10. #define DHT11_Read() (DHT11_GPIO_Port->IDR & DHT11_Pin) /*HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin)*/
  11. #define DHT11_High() DHT11_GPIO_Port->ODR |= (0x01 << DHT11_Pin_Location)
  12. #define DHT11_Low() DHT11_GPIO_Port->ODR &= ~(0x01 << DHT11_Pin_Location) /*HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET)*/
  13. #define DHT11_Wait_Low() while (DHT11_Read())
  14. #define DHT11_Wait_High() while (!DHT11_Read())
  15. #define DHT11_IN()                                                  \
  16.     {                                                               \
  17.         DHT11_GPIO_Port->MODER &= ~(3 << (2 * DHT11_Pin_Location)); \
  18.         DHT11_GPIO_Port->MODER |= 0 << 2 * DHT11_Pin_Location;      \
  19.     }
  20. #define DHT11_OUT()                                                 \
  21.     {                                                               \
  22.         DHT11_GPIO_Port->MODER &= ~(3 << (2 * DHT11_Pin_Location)); \
  23.         DHT11_GPIO_Port->MODER |= 1 << 2 * DHT11_Pin_Location;      \
  24.     }
  25. //static uint16_t std_delay_80us = 875;//事先测试过
  26. //static uint16_t std_delay_50us = 566;
  27. /**动态计算延时,以确保任何情况下都可以得到较为准确的延时*/
  28. //void std_delay_us(uint8_t us)
  29. //{
  30. //    //   uint16_t count = std_delay_80us * us / 80;//测试得到的
  31. //    uint16_t count = 11 * us;
  32. //    for (uint16_t i = 0; i < count; ++i)
  33. //        ;
  34. //}
  35. inline void std_delay_25us()
  36. {
  37.     for (uint16_t i = 0; i < 20; ++i)//单个任务时,大概为273
  38.         ;
  39. }
  40. void DHT11_Init()
  41. {
  42.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  43.     DHT11_GPIO_CLK_ENABLE();
  44.     GPIO_InitStruct.Pin = DHT11_Pin;
  45.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  46.     GPIO_InitStruct.Pull = GPIO_PULLUP;
  47.     //    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;//输入模式下,最好不要配置速度,所以为了兼容输入就不配置了,即默认2MHz
  48.     HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
  49.     DHT11_High();
  50. }
  51. inline void DHT11_Rst()
  52. {
  53.     DHT11_OUT();
  54.     DHT11_Low();
  55.     osDelay(25);//根据时序图可知,需要至少拉低18ms
  56.     DHT11_High();
  57.     std_delay_25us();//20-40us
  58. }
  59. inline void DHT11_Check()
  60. {
  61.     DHT11_IN();
  62.     //等待低电平
  63.     DHT11_Wait_Low();
  64.     //等待高电平
  65.     DHT11_Wait_High();
  66.     // 等待低电平
  67.     DHT11_Wait_Low();
  68. }
  69. #if USE_YZHX == 0
  70. bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
  71. {
  72.     static uint8_t buf[5];
  73.     DHT11_Rst();  // 设置输出模式
  74.     DHT11_Check();// 设置输入模式
  75.     for (unsigned char &i: buf)// 读取40位数据
  76.     {
  77.         uint8_t data = 0;
  78.         for (uint8_t j = 0; j < 8; j++)
  79.         {
  80.             data <<= 1;
  81.             while (DHT11_Read()) {} // 等待低电平
  82.             while (!DHT11_Read()) {}// 等待变高电平
  83.             // 开始读数据
  84.             uint16_t time_count;
  85.             for (time_count = 0; DHT11_Read(); ++time_count) {}
  86.             data |= time_count >> 10;// 由于事先已经知道一个为1194,一个为406左右
  87.         }
  88.         i = data;// 存储数据
  89.     }
  90.     if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
  91.     {
  92.         humi = (buf[0] * 10 + buf[1]) / 10.0f;
  93.         temp = (buf[2] * 10 + buf[3]) / 10.0f;
  94.         return true;
  95.     }
  96.     else
  97.     {
  98.         return false;
  99.     }
  100. }
  101. #endif
  102. /********************下面为次优级优化********************/
  103. #if USE_YZHX == 1
  104. // 全局变量
  105. static uint8_t timeBuf[40];// 存储计数值
  106. static uint8_t timeBufIndex = 0;
  107. //void DHT11_Read_Byte_Fast_Pro()
  108. //{
  109. //    for (uint8_t i = 0; i < 8; i++)
  110. //    {
  111. //        while (DHT11_Read()) {} // 等待低电平
  112. //        while (!DHT11_Read()) {}// 等待变高电平
  113. //
  114. //        // 开始读数据
  115. //        uint16_t time_count;
  116. //        for (time_count = 0; DHT11_Read(); ++time_count) {}
  117. //        timeBuf[timeBufIndex++] = time_count>>4;// 存储计数值,由于事先已经知道一个为875,一个为275左右,所以除以16
  118. //    }
  119. //}
  120. bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
  121. {
  122.     static uint8_t buf[5];
  123.     DHT11_Rst();  // 设置输出模式
  124.     DHT11_Check();// 设置输入模式
  125.     timeBufIndex = 0;          // 重置计数值索引
  126.     for (unsigned char &i: buf)// 读取40位数据
  127.     {
  128.         //        DHT11_Read_Byte_Fast_Pro();
  129.         //读取一字节
  130.         for (uint8_t j = 0; j < 8; j++)
  131.         {
  132.             DHT11_Wait_High();// 等待变高电平
  133.             // 开始读数据
  134.             uint16_t time_count = 0;
  135.             for (; DHT11_Read() && time_count < DHT11_MAX_DELAY_COUNT; ++time_count) {}
  136.             if (time_count >= DHT11_MAX_DELAY_COUNT)
  137.             {
  138.                 return false;
  139.             }
  140.             timeBuf[timeBufIndex++] = time_count >> 4;// 存储计数值,由于事先已经知道一个为875,一个为275左右,所以除以16
  141.         }
  142.     }
  143.     //    std_delay_25us();
  144.     //    std_delay_25us();
  145.     //    DHT11_OUT();
  146.     //    DHT11_High();
  147.     uint16_t timeMax = 0;
  148.     uint16_t timeMin = 0xFFFF;
  149.     for (unsigned short i: timeBuf)
  150.     {
  151.         if (i > timeMax) timeMax = i;
  152.         if (i < timeMin) timeMin = i;
  153.     }
  154.     uint16_t timeMed = (timeMax + timeMin) >> 1;// 取中位数
  155.     for (uint8_t i = 0; i < 5; ++i)
  156.     {
  157.         uint8_t data = 0;
  158.         for (uint8_t j = 0; j < 8; j++)
  159.         {
  160.             data <<= 1;
  161.             data |= (timeBuf[i * 8 + j] > timeMed);
  162.         }
  163.         buf[i] = data;// 存储数据
  164.     }
  165.     if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
  166.     {
  167.         humi = (buf[0] * 10 + buf[1]) / 10.0f;
  168.         temp = (buf[2] * 10 + buf[3]) / 10.0f;
  169.         return true;
  170.     }
  171.     else
  172.     {
  173.         return false;
  174.     }
  175. }
  176. #endif
  177. #if USE_YZHX == 2
  178. static uint16_t timeBuf[40];//存储计数值
  179. static uint8_t timeBufIndex = 0;
  180. void DHT11_Read_Byte_Fast_Pro()
  181. {
  182.     for (uint8_t i = 0; i < 8; i++)
  183.     {
  184.         while (DHT11_Read())
  185.             ;//等待低电平
  186.         //变低了说明上一次数据位读取结束
  187.         while (!DHT11_Read())
  188.             ;//等待变高电平
  189.         //变高了说明数据位读取开始
  190.         /**开始读数据*/
  191.         //低电平:26-28us   高电平:70us
  192.         uint16_t time_count;
  193.         for (time_count = 0; DHT11_Read(); ++time_count)
  194.             ;                                //等待低电平
  195.         timeBuf[timeBufIndex++] = time_count;//存储计数值//存储计数值
  196.     }
  197. }
  198. bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
  199. {
  200.     static uint8_t buf[5];
  201.     DHT11_Rst();               //在里面设置了输出模式
  202.     DHT11_Check();             //在里面设置了输入模式
  203.                                //  return false;//如果超时,则退出
  204.     timeBufIndex = 0;          //存储计数值索引
  205.     for (unsigned char &i: buf)//读取40位数据
  206.     {
  207.         DHT11_Read_Byte_Fast_Pro();
  208.     }
  209.     uint16_t timeMax = 0;
  210.     uint16_t timeMin = 0xFFFF;
  211.     for (unsigned short i: timeBuf)
  212.     {
  213.         if (i > timeMax)
  214.         {
  215.             timeMax = i;
  216.         }
  217.         else if (i < timeMin)
  218.         {
  219.             timeMin = i;
  220.         }
  221.     }
  222.     /**把计数值转为二进制数据*/
  223.     uint8_t data;                               //临时数据
  224.     uint16_t timeMed = (timeMax + timeMin) >> 1;//整除2,取中位数
  225.     bool tempBin;
  226.     for (uint8_t i = 0; i < 5; ++i)
  227.     {
  228.         data = 0;
  229.         for (uint8_t j = 0; j < 8; j++)
  230.         {
  231.             data <<= 1;
  232.             //比较计数值,读取二进制数据
  233.             if (timeBuf[i * 8 + j] > timeMed)
  234.             {
  235.                 tempBin = true;
  236.             }
  237.             else
  238.             {
  239.                 tempBin = false;
  240.             }
  241.             data |= tempBin;
  242.         }
  243.         buf[i] = data;//存储数据
  244.     }
  245.     /**检验**/
  246.     if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
  247.     {
  248.         humi = (float) (buf[0] + buf[1] * 0.1);
  249.         temp = (float) (buf[2] + buf[3] * 0.1);
  250.         return true;
  251.     }
  252.     else
  253.     {
  254.         return false;
  255.     }
  256. }
  257. #endif
  258. /********************下面为原版优化********************/
  259. #if USE_YZHX == 3
  260. static uint16_t timeBuf[40];//存储计数值
  261. void DHT11_Read_Byte_Fast_Pro()
  262. {
  263.     static uint8_t timeBufIndex = 0;//存储计数值索引
  264.     for (uint8_t i = 0; i < 8; i++)
  265.     {
  266.         while (DHT11_Read())
  267.             ;//等待低电平
  268.         //变低了说明上一次数据位读取结束
  269.         while (!DHT11_Read())
  270.             ;//等待变高电平
  271.         //变高了说明数据位读取开始
  272.         /**开始读数据*/
  273.         //低电平:26-28us   高电平:70us
  274.         uint16_t time_count;
  275.         for (time_count = 0; DHT11_Read(); ++time_count)
  276.             ;                                //等待低电平
  277.         timeBuf[timeBufIndex++] = time_count;//存储计数值
  278.     }
  279. }
  280. bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
  281. {
  282.     static uint8_t buf[5];
  283.     static uint16_t timeMax = 0;
  284.     static uint16_t timeMin = 0xFFFF;
  285.     DHT11_Rst();               //在里面设置了输出模式
  286.     DHT11_Check();             //在里面设置了输入模式
  287.                                //  return false;//如果超时,则退出
  288.     for (unsigned char &i: buf)//读取40位数据
  289.     {
  290.         DHT11_Read_Byte_Fast_Pro();
  291.     }
  292.     for (unsigned short i: timeBuf)
  293.     {
  294.         if (i > timeMax)
  295.         {
  296.             timeMax = i;
  297.         }
  298.         else
  299.         {
  300.             timeMin = i;
  301.         }
  302.     }
  303.     std_delay_25us();
  304.     std_delay_25us();
  305.     DHT11_OUT();
  306.     DHT11_High();
  307.     /**把计数值转为二进制数据*/
  308.     uint16_t timeMed = (timeMax + timeMin) >> 1;//整除2,取中位数
  309.     uint8_t data;                               //临时数据
  310.     bool tempBin;                               //临时二进制数据
  311.     for (int i = 0; i < 5; ++i)
  312.     {
  313.         data = 0;//重置
  314.         for (int j = 0; j < 8; ++j)
  315.         {
  316.             data <<= 1;
  317.             //比较计数值,读取二进制数据
  318.             if (timeBuf[i * 8 + j] > timeMed)
  319.             {
  320.                 tempBin = true;
  321.             }
  322.             else
  323.             {
  324.                 tempBin = false;
  325.             }
  326.             data |= tempBin;
  327.         }
  328.         buf[i] = data;//存储数据
  329.     }
  330.     /**检验**/
  331.     if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
  332.     {
  333.         humi = (float) (buf[0] + buf[1] * 0.1);
  334.         temp = (float) (buf[2] + buf[3] * 0.1);
  335.         return true;
  336.     }
  337.     else
  338.     {
  339.         return false;
  340.     }
  341. }
  342. #endif
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

万万哇

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表