1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
背景说明
先进先出队列(简称队列)是一种基于先进先出(FIFO)策略的集合类型。对于数据传输速度不同步的应用场景里,采用FIFO队列作为数据缓冲是十分有必要的。在单片机开发的项目中,笔者遇见应用FIFO缓冲的两个典型场景分别是串口数据收发与ADC高速采样。 FIFO队列最重要的指标之一就是队列长度问题,因为队列长度是有限的,有可能被填满,这就涉及到该机制的丢弃原则。常见的一个丢弃原则叫做Tail Drop机制,简单地说就是该队列如果已经满了,那么后续进入的报文被丢弃。还有一种原则是覆盖机制,简单的说就是如果队列已经满了,那么后续进入的数据将覆盖最前面的数据,队列中的数据始终保持着最新。 两种机制有各自的应用场景,但当队列已满时,都有不可避免的数据丢失。因此,在硬件资源足够的前提下,可以适当增大队列的深度,提高读操作的速度,以尽量避免队列满的情况。本文设计的FIFO队列模型采用了覆盖机制,读者可以根据需要将它改成Tail Drop机制。 库源码 头文件 /* * fifo.h * * Created on: 2020年9月18日 * Author: Tao */ #ifndef SOURCE_ALWHALESLIB_SYSEXTEND_INC_FIFO_H_ #define SOURCE_ALWHALESLIB_SYSEXTEND_INC_FIFO_H_ #include "stm32f4xx.h" #include "stm32f4xx_conf.h" /** * 考虑到FIFO数据成员可能会是不同类型的数据, * 因此在此处重命名一个数据类型, * 并将此数据类型作为FIFO数据结构库的成员类型。 * 这么做的好处是可以方便的修改FIFO的成员数据类型。 */ typedef uint16_t FIFO_DataType; typedef struct { uint32_t BufferSize; //数据缓存容量 FIFO_DataType *Buffer; //数据缓存 FIFO_DataType *Read_P; //读指针 FIFO_DataType *Write_P; //写指针 uint32_t DataCount; //剩余数据量 } FIFO_Struct; #define FIFO_DATA_NUM 1 #define FIFO_DATA_SIZE 10000 extern FIFO_Struct FIFO_Data[FIFO_DATA_NUM]; void FIFO_Init(FIFO_Struct *FIFO_Data); void FIFO_WriteData(FIFO_Struct *FIFO_Data,FIFO_DataType *Data, uint32_t length); void FIFO_WriteOneData(FIFO_Struct *FIFO_Data,FIFO_DataType Data); void FIFO_ReadData(FIFO_Struct *FIFO_Data,FIFO_DataType *Data, uint32_t length); uint16_t FIFO_ReadOneData(FIFO_Struct *FIFO_Data); uint8_t FIFO_IsDataFull(FIFO_Struct *FIFO_Data); uint8_t FIFO_IsDataEmpty(FIFO_Struct *FIFO_Data); uint32_t FIFO_GetDataCount(FIFO_Struct *FIFO_Data); #endif /* SOURCE_ALWHALESLIB_SYSEXTEND_INC_FIFO_H_ */ 源文件 /* * fifo.c * * Created on: 2020年9月18日 * Author: Tao */ #include "fifo.h" static FIFO_DataType FIFO_DataBuffer[FIFO_DATA_NUM][FIFO_DATA_SIZE]; FIFO_Struct FIFO_Data[FIFO_DATA_NUM] = { { .BufferSize = FIFO_DATA_SIZE, .Buffer = FIFO_DataBuffer[0], }, }; /** * @brief 初始化FIFO队列数据:清空数据、复位读写指针 */ void FIFO_Init(FIFO_Struct *FIFO_Data) { FIFO_Data->DataCount = 0; FIFO_Data->Read_P = FIFO_Data->Buffer; FIFO_Data->Write_P = FIFO_Data->Buffer; } /** * @brief 将数据写入FIFO队列,当数据超出缓冲区的大小时,停止写入数据 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @param Data: 需要写入的数据指针 * @param length: 需要写入的数据长度 */ void FIFO_WriteData(FIFO_Struct *FIFO_Data,FIFO_DataType *Data, uint32_t length) { //将数据依次写入到队列缓冲区 for(uint32_t index = 0; index < length; index++) { //如果计数器大于等于缓冲容量 if(FIFO_Data->DataCount > FIFO_Data->BufferSize -1) { //退出写数据 return; } //写入一个数据 *FIFO_Data->Write_P = *Data; //写指针移动一位 FIFO_Data->Write_P++; //数据缓存指针移动一位 Data++; //计数器自增1 FIFO_Data->DataCount++; //如果写指针已经到达缓冲区边界 if(FIFO_Data->Write_P >= FIFO_Data->Buffer + FIFO_Data->BufferSize) { //使写指针回到缓冲区起点 FIFO_Data->Write_P = FIFO_Data->Buffer; } } } /** * @brief 向FIFO队列中写入一个数据 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @param Data: 要写入的数据 */ void FIFO_WriteOneData(FIFO_Struct *FIFO_Data,FIFO_DataType Data) { FIFO_WriteData(FIFO_Data, &Data, 1); } /** * @brief 将数据从FIFO队列中读出,当缓冲区为空时,停止读出数据 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @param Data: 用来存放读出数据的指针 * @param length: 需要读出的数据长度 */ void FIFO_ReadData(FIFO_Struct *FIFO_Data,FIFO_DataType *Data, uint32_t length) { //将缓冲区数据依次读出到Data数组中 for(uint32_t index = 0; index < length; index++) { //缓冲区数据计数器为0时 if(FIFO_Data->DataCount == 0) { //退出读数据 return; } //如果数据计数器大于写指针减去缓冲区起始位置(说明写入的数据已经到达过缓冲区边界) if(FIFO_Data->Write_P - FIFO_Data->Buffer < FIFO_Data->DataCount) { //确定数据初始位置,并传递给读指针 FIFO_Data->Read_P = FIFO_Data->BufferSize - FIFO_Data->DataCount + FIFO_Data->Write_P; } //写入的数据还未到达过缓冲区边界 else { //确定数据初始位置,并传递给读指针 FIFO_Data->Read_P = FIFO_Data->Write_P - FIFO_Data->DataCount; } //读出一个数据 *Data = *FIFO_Data->Read_P; //读指针移动一位 FIFO_Data->Read_P++; //数据缓存指针移动一位 Data++; //计数器自减1 FIFO_Data->DataCount--; //如果读指针已经到达缓冲区边界 if(FIFO_Data->Read_P >= FIFO_Data->Buffer + FIFO_Data->BufferSize) { //使读指针回到缓冲区起点 FIFO_Data->Read_P = FIFO_Data->Buffer; } } } /** * @brief 从FIFO队列中读出一个数据 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @retval 读出的数据 */ FIFO_DataType FIFO_ReadOneData(FIFO_Struct *FIFO_Data) { FIFO_DataType tempData; FIFO_ReadData(FIFO_Data, &tempData, 1); return tempData; } /** * @brief 判断队列数据是否已满 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @retval 指示队列是否已满 * @arg 0: 队列未满 * @arg 1: 队列已满 */ uint8_t FIFO_IsDataFull(FIFO_Struct *FIFO_Data) { if(FIFO_Data->DataCount >= FIFO_Data->BufferSize) { return 1; } else { return 0; } } /** * @brief 判断队列数据是否为空 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @retval 指示队列是否为空 * @arg 0: 队列不空 * @arg 1: 队列为空 */ uint8_t FIFO_IsDataEmpty(FIFO_Struct *FIFO_Data) { if(FIFO_Data->DataCount == 0) { return 1; } else { return 0; } } /** * @brief 获取队列数据的数量 * @param FIFO_Data: 需要操作的FIFO队列数据指针 * @retval 队列数据的数量 */ uint32_t FIFO_GetDataCount(FIFO_Struct *FIFO_Data) { return FIFO_Data->DataCount; } 应用指南
#define FIFO_DATA_NUM 2 #define FIFO_DATA_SIZE 10000 extern FIFO_Struct FIFO_Data[FIFO_DATA_NUM]; FIFO_Struct FIFO_Data[FIFO_DATA_NUM] = { { .BufferSize = FIFO_DATA_SIZE, .Buffer = FIFO_DataBuffer[0], }, { .BufferSize = FIFO_DATA_SIZE, .Buffer = FIFO_DataBuffer[1], }, }; void User_Init() { /*省略无关代码*/ FIFO_Init(&FIFO_Data[0]); FIFO_Init(&FIFO_Data[1]); /*省略无关代码*/ }
/** * @brief 在外部中断14的服务函数中周期性的写入AD7606的高速采样数据 */ void EXTI14Triggered() { if(User_StartDAQ != 0) { AD7606_RefreshData(); FIFO_WriteOneData(&FIFO_Data[0], AD7606_RawData[0]); } }
/** * @brief This function is called by timer update interrupt handler, which will be executed periodically. */ void User_RefreshData() { //注意SensorData数组顺序与ADS1115数据通道顺序不一致 SensorData[0].value = ADS1115_Data[1]; SensorData[1].value = ADS1115_Data[0]; //注意SensorData数组顺序与AD7606数据通道顺序不一致 SensorData[2].value = (int16_t)AD7606_RawData[1]/32768.0*5000; SensorData[3].value = (int16_t)FIFO_ReadOneData(&FIFO_Data[0])/32768.0*5000; User_SetOutputCurrent(); User_RefreshSingalSwitch(); }
typedef float FIFO_DataType; |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1767 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1069 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1935浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
726浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
592浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
551浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 18:31 , Processed in 0.885997 second(s), Total 76, Slave 60 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号