当前位置: 首页 > news >正文

市体育局网站 两学一做最新的全国疫情

市体育局网站 两学一做,最新的全国疫情,深圳网站网站建设,带分销系统的微商城设备:stm32f407ZGT6 环境:FreeRTOS HAL 到网上找DHT11的驱动,但是都无法使用。原因是RTOS环境中,由于多线程,使用循环计数阻塞式的delay_us延时函数就没那么准,且不同设备中delay_us的计数值不一样…

设备:stm32f407ZGT6

环境:FreeRTOS        HAL

        到网上找DHT11的驱动,但是都无法使用。原因是RTOS环境中,由于多线程,使用循环计数阻塞式的delay_us延时函数就没那么准,且不同设备中delay_us的计数值不一样。而DHT11对时序要求得又十分严格,这就会导致读取数据异常,甚至无法读取。

        虽然考虑过使用其他方法达成更精准的微秒级延时,但是对于单总线传输终归小题大做了。于是下面就简单的使用计数值来模拟延时,不需要考虑延时多少微秒,只需要比较高电平持续时间的相对长短。

/**********************************************************************************************************
函数名称:us延时函数,最小延时为1us
输入参数:时间
输出参数:无
**********************************************************************************************************/
void delay_us(unsigned int time)
{unsigned short i = 0;while (time--){i = 8;while (i--);}
}

需要注意的是,下面代码使用的是C++,如果你使用的是C,那么用相应功能的代码替换掉即可。bool类型需要包含stdbool头文件

DHT11.h

        头文件里未被注释的接口,决定了哪些函数需要重点关注

#ifndef DHT11_H
#define DHT11_Hvoid DHT11_Init();
//bool DHT11_Read_Data(float &temp,float &humi);
bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi);//自定义的快速读取函数
#endif//DHT11_H

DHT11.cpp

        里面的这个std_delay_us是用于调试中用的,在void DHT11_Rst()函数里,你把延时换成你自带的即可,这个不需要多精准。

        下面的函数是与时序图直接对应的,连续读取温度时,最好间隔1s以上

        同时说明一下,下面将作为反面例子!!,找了许久才发现是数组越界引发的硬件中断,下面代码忘了对timeBufIndex清零。后面我会发一个简化版

#include "DHT11.h"
#include "cmsis_os2.h"
#include "stm32f4xx_hal.h"#define DHT11_Pin GPIO_PIN_6
#define DHT11_GPIO_Port GPIOE
#define DHT11_GPIO_CLK_ENABLE() __HAL_RCC_GPIOE_CLK_ENABLE()#define DHT11_Read()  (DHT11_GPIO_Port->IDR & DHT11_Pin) /*HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin)*/
#define DHT11_Write(x) HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, (GPIO_PinState) (x))#define DHT11_High() HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_SET)
#define DHT11_Low() HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET)static GPIO_InitTypeDef GPIO_InitStruct = {0};
static uint16_t std_delay_80us=875;//事先测试过
static uint16_t std_delay_50us=566;
static uint16_t time_count;/**动态计算延时,以确保任何情况下都可以得到较为准确的延时*/
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);
}/**函数*/
void DHT11_Input();
void DHT11_Output();
void DHT11_Rst();void DHT11_Init()
{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_HIGH;HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);DHT11_High();
}void DHT11_Input()
{GPIO_InitStruct.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
}void DHT11_Output()
{GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
}void DHT11_Rst()
{DHT11_Output();DHT11_Low();osDelay(25);//根据时序图可知,需要至少拉低18msDHT11_High();std_delay_us(20);//20-40us
}void DHT11_Check()
{DHT11_Input();for (time_count =0;DHT11_Read();++time_count);/* 等待DHT11数据线拉低 */for (time_count =0;!DHT11_Read();++time_count);  /* 等待DHT11数据线拉高 *///持续80usstd_delay_80us = time_count;//获取80us需要的计数值
}//从DHT11读取一个位
//返回值:1/0
uint8_t DHT11_Read_Bit()
{for (time_count =0;DHT11_Read();++time_count);//等待低电平//变低了说明上一次数据位读取结束for (time_count =0;!DHT11_Read();++time_count); //等待变高电平// std_delay_50us = time_count;//测试用的//变高了说明数据位读取开始/**开始读数据*///低电平:26-28us//高电平:70usstd_delay_us(40);// 等待40us,如果延时准确的话if (DHT11_Read())return 1;elsereturn 0;
}//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte()
{uint8_t dat = 0;for (uint8_t i = 0; i < 8; i++){dat <<= 1;dat |= DHT11_Read_Bit();}return dat;
}//uint16_t timeBuf[40];
//uint8_t timeBufIndex=0;
//uint16_t timeMax=0;
//uint16_t timeMin=10000;
//uint8_t DHT11_Read_Byte_Fast()
//{
//    uint8_t  dat=0;
//    for (uint8_t i = 0; i < 8; i++)
//    {
//        for (time_count =0;DHT11_Read();++time_count);//等待低电平
//        //变低了说明上一次数据位读取结束
//
//        for (time_count =0;!DHT11_Read();++time_count); //等待变高电平
//             // std_delay_50us = time_count;//测试用的
//        //变高了说明数据位读取开始
//
//        /**开始读数据*/
//        //低电平:26-28us   高电平:70us
//        for (time_count =0;DHT11_Read();++time_count);//等待低电平
//        timeBuf[timeBufIndex++]=time_count;
//    //    std_delay_us(30);// 等待40us,如果延时准确的话
//        dat <<= 1;
//        dat |= DHT11_Read();
//    }
//    return dat;
//}uint16_t timeBuf[40];//存储计数值
uint8_t timeBufIndex=0;//存储计数值索引
uint16_t timeMax=0;
uint16_t timeMin=0xFFFF;
void DHT11_Read_Byte_Fast_Pro()
{for (uint8_t i = 0; i < 8; i++){for (time_count =0;DHT11_Read();++time_count);//等待低电平//变低了说明上一次数据位读取结束for (time_count =0;!DHT11_Read();++time_count); //等待变高电平//变高了说明数据位读取开始/**开始读数据*///低电平:26-28us   高电平:70usfor (time_count =0;DHT11_Read();++time_count);//等待低电平timeBuf[timeBufIndex++]=time_count;//存储计数值}
}bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
{uint8_t buf[5];DHT11_Rst();DHT11_Check();for (unsigned char & i : buf)//读取40位数据{DHT11_Read_Byte_Fast_Pro();}for (unsigned short i : timeBuf){if(i>timeMax){timeMax=i;}else if(i<timeMin){timeMin=i;}}/**把计数值转为二进制数据*/uint16_t timeMed=(timeMax+timeMin)>>1;//整除2,取中位数uint8_t data;//临时数据bool tempBin;//临时二进制数据for (int i = 0; i < 5; ++i){data=0;//重置for (int j = 0; j < 8; ++j){data<<=1;//比较计数值,读取二进制数据if(timeBuf[i*8+j]>timeMed){tempBin= true;}else{tempBin= false;}data|=tempBin;}buf[i]=data;//存储数据}/**检验**/if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]){humi = (float) (buf[0] + buf[1] * 0.1);temp = (float) (buf[2] + buf[3] * 0.1);return true;}else{return false;}
}//bool DHT11_Read_Data(float &temp, float &humi)
//{
//    uint8_t buf[5];
//    DHT11_Rst();
//    DHT11_Check();
//    for (unsigned char & i : buf)//读取40位数据
//    {
//        i = DHT11_Read_Byte_Fast();
//    }
//
//    for (unsigned short i : timeBuf)
//    {
//        if(i>timeMax)
//        {
//            timeMax=i;
//        }
//        else if(i<timeMin)
//        {
//            timeMin=i;
//        }
//    }
//
//    uint16_t timeMed=(timeMax+timeMin)>>1;
//    uint8_t data;
//    uint8_t tempBin;
//    uint8_t tempBuf[5];
//    for (int i = 0; i < 5; ++i)
//    {
//        data=0;
//        for (int j = 0; j < 8; ++j)
//        {
//            data<<=1;
//            if(timeBuf[i*8+j]>timeMed)
//            {
//                tempBin=1;
//            }
//            else
//            {
//                tempBin=0;
//            }
//            data|=tempBin;
//        }
//        tempBuf[i]=data;
//    }
//
//    //检验
//    if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
//    {
//        humi = (float) (buf[0] + buf[1] * 0.1);
//        temp = (float) (buf[2] + buf[3] * 0.1);
//        return true;
//    }
//    else
//    {
//        return false;
//    }
//}

修正版。里面有三个版本,没被注释的是特化版本,其下愈为通用

#include "DHT11.h"
#include "cmsis_os2.h"
#include "delay.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;/**动态计算延时,以确保任何情况下都可以得到较为准确的延时*/
//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)
//        ;
//}
inline void std_delay_25us()
{for (uint16_t i = 0; i < 273; ++i);
}/**函数*/
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);//根据时序图可知,需要至少拉低18msDHT11_High();std_delay_25us();//20-40us
}inline void DHT11_Check()
{DHT11_IN();while (DHT11_Read());while (!DHT11_Read());
}bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
{static uint8_t buf[5];DHT11_Rst();  // 设置输出模式DHT11_Check();// 设置输入模式for (unsigned char & i : buf)// 读取40位数据{uint8_t data=0;for (uint8_t j = 0; j < 8; j++){data<<=1;while (DHT11_Read()) {} // 等待低电平while (!DHT11_Read()) {}// 等待变高电平// 开始读数据uint16_t time_count;for (time_count = 0; DHT11_Read(); ++time_count) {}data|=time_count>>10;// 由于事先已经知道一个为1194,一个为406左右}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;}
}/********************下面为次优级优化********************/全局变量
//static uint8_t timeBuf[40];// 存储计数值
//static uint8_t timeBufIndex = 0;
//
//void DHT11_Read_Byte_Fast_Pro()
//{
//    for (uint8_t i = 0; i < 8; i++)
//    {
//        while (DHT11_Read()) {} // 等待低电平
//        while (!DHT11_Read()) {}// 等待变高电平
//
//        // 开始读数据
//        uint16_t time_count;
//        for (time_count = 0; DHT11_Read(); ++time_count) {}
//        timeBuf[timeBufIndex++] = time_count>>4;// 存储计数值,由于事先已经知道一个为875,一个为275左右,所以除以16
//    }
//}
//
//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();
//    }
//
//    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;
//    }
//}//
//static uint16_t timeBuf[40];//存储计数值
//static uint8_t timeBufIndex = 0;
//void DHT11_Read_Byte_Fast_Pro()
//{
//    for (uint8_t i = 0; i < 8; i++)
//    {
//        while (DHT11_Read())
//            ;//等待低电平
//        //变低了说明上一次数据位读取结束
//
//        while (!DHT11_Read())
//            ;//等待变高电平
//        //变高了说明数据位读取开始
//
//        /**开始读数据*/
//        //低电平:26-28us   高电平:70us
//        uint16_t time_count;
//        for (time_count = 0; DHT11_Read(); ++time_count)
//            ;                                //等待低电平
//        timeBuf[timeBufIndex++] = time_count;//存储计数值//存储计数值
//    }
//}
//
//
//bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
//{
//    static uint8_t buf[5];
//
//    DHT11_Rst();               //在里面设置了输出模式
//    DHT11_Check();             //在里面设置了输入模式
//                               //  return false;//如果超时,则退出
//    timeBufIndex = 0;          //存储计数值索引
//    for (unsigned char &i: buf)//读取40位数据
//    {
//        DHT11_Read_Byte_Fast_Pro();
//    }
//
//    uint16_t timeMax = 0;
//    uint16_t timeMin = 0xFFFF;
//    for (unsigned short i: timeBuf)
//    {
//        if (i > timeMax)
//        {
//            timeMax = i;
//        }
//        else if(i<timeMin)
//        {
//            timeMin = i;
//        }
//    }
//
//    /**把计数值转为二进制数据*/
//    uint8_t data;                                     //临时数据
//    uint16_t timeMed = (timeMax + timeMin) >> 1;//整除2,取中位数
//    bool tempBin;
//    for (uint8_t i = 0; i < 5; ++i)
//    {
//        data = 0;
//        for (uint8_t j = 0; j < 8; j++)
//        {
//            data <<= 1;
//            //比较计数值,读取二进制数据
//            if (timeBuf[i * 8 + j] > timeMed)
//            {
//                tempBin = true;
//            }
//            else
//            {
//                tempBin = false;
//            }
//            data |= tempBin;
//        }
//        buf[i] = data;//存储数据
//    }
//
//    /**检验**/
//    if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
//    {
//        humi = (float) (buf[0] + buf[1] * 0.1);
//        temp = (float) (buf[2] + buf[3] * 0.1);
//        return true;
//    }
//    else
//    {
//        return false;
//    }
//}/********************下面为原版优化********************/
//static uint16_t timeBuf[40];//存储计数值
//
//void DHT11_Read_Byte_Fast_Pro()
//{
//    static uint8_t timeBufIndex = 0;//存储计数值索引
//    for (uint8_t i = 0; i < 8; i++)
//    {
//        while (DHT11_Read())
//            ;//等待低电平
//        //变低了说明上一次数据位读取结束
//
//        while (!DHT11_Read())
//            ;//等待变高电平
//        //变高了说明数据位读取开始
//
//        /**开始读数据*/
//        //低电平:26-28us   高电平:70us
//        uint16_t time_count;
//        for (time_count = 0; DHT11_Read(); ++time_count)
//            ;                                //等待低电平
//        timeBuf[timeBufIndex++] = time_count;//存储计数值
//    }
//}
//
//
//bool DHT11_Read_Data_Fast_Pro(float &temp, float &humi)
//{
//    static uint8_t buf[5];
//    static uint16_t timeMax = 0;
//    static uint16_t timeMin = 0xFFFF;
//
//    DHT11_Rst();               //在里面设置了输出模式
//    DHT11_Check();             //在里面设置了输入模式
//                               //  return false;//如果超时,则退出
//    for (unsigned char &i: buf)//读取40位数据
//    {
//        DHT11_Read_Byte_Fast_Pro();
//    }
//
//    for (unsigned short i: timeBuf)
//    {
//        if (i > timeMax)
//        {
//            timeMax = i;
//        }
//        else
//        {
//            timeMin = i;
//        }
//    }
//    std_delay_25us();
//    std_delay_25us();
//    DHT11_OUT();
//    DHT11_High();
//
//
//    /**把计数值转为二进制数据*/
//    uint16_t timeMed = (timeMax + timeMin) >> 1;//整除2,取中位数
//    uint8_t data;                               //临时数据
//    bool tempBin;                               //临时二进制数据
//    for (int i = 0; i < 5; ++i)
//    {
//        data = 0;//重置
//        for (int j = 0; j < 8; ++j)
//        {
//            data <<= 1;
//            //比较计数值,读取二进制数据
//            if (timeBuf[i * 8 + j] > timeMed)
//            {
//                tempBin = true;
//            }
//            else
//            {
//                tempBin = false;
//            }
//            data |= tempBin;
//        }
//        buf[i] = data;//存储数据
//    }
//
//    /**检验**/
//    if ((buf[0] + buf[1] + buf[2] + buf[3]) == buf[4])
//    {
//        humi = (float) (buf[0] + buf[1] * 0.1);
//        temp = (float) (buf[2] + buf[3] * 0.1);
//        return true;
//    }
//    else
//    {
//        return false;
//    }
//}

http://www.dinnco.com/news/24938.html

相关文章:

  • 网站建站的步骤找营销推广团队
  • 支付网站备案成都疫情最新消息
  • 北京做网站推广seo电脑培训学校
  • 网站优化及推广seo在线网站推广
  • 网站建设的企业目标百度搜索关键词排名优化
  • 企业网站 设计广州代运营公司有哪些
  • 大宗商品采购平台杭州百度seo优化
  • 江苏省教育网站官网创建网站要钱吗
  • 郑州微网站建设俄罗斯引擎搜索
  • 哪家建公司网站互联网营销师是干什么
  • b2b网站开发商需求分析自己代理一款手游需要多少钱
  • 北京网站建设 都选万维科技中国市场营销网
  • 做网站的叫什么职位企业关键词优化最新报价
  • 做爰片免费观看网站qq群怎么优化排名靠前
  • 网站建设的项目总结站长之家统计
  • seo网站建设方案站长工具seo排名查询
  • 网站开发需要学什么技能巨量千川广告投放平台
  • 企业手机网站案例seo推广软件排行榜
  • 药企网站怎么做属于网络营销的特点是
  • 做网站用动易siteweaver cms还是phpcms微营销官网
  • wordpress建设QQ登录廊坊首页霸屏优化
  • 自己做网站卖阀门网站产品怎么优化
  • 想做网站建设关键词排名优化易下拉排名
  • 求网站爱廷玖达泊西汀
  • 自己怎么做VIP视频解网站seo诊断
  • html5结构的网站百度指数排名热搜榜
  • 新手学做网站 cs5 pdfseo人才
  • 百度收录了我新网站的2篇文章了培训课
  • 定制 网站以下属于网站seo的内容是
  • 新疆住建厅八大员报名网站seo工作职位