前言

嵌入式开发过程中,各个模块之间,各个设备之间进行交互时,都会存在数据的输入输出,由于处理的方式不同,数据不会立即同步处理,因此通常在设计时都会设计缓冲区进行数据的处理,方式数据丢失等问题;一个项目中存在不同模块都需要缓冲区的设计,设计策略基本都一样,不同的是数据结构,在 C 语言中可以编写缓冲区功能函数,入参类型通常为无类型指针,适配所有需要储存的不同数据结构,但是这种方式必须先知道不同数据结构体的大小,在写入和读取时按一个个字节操作。

下面介绍的是使用宏定义函数实现该方式,按照数据结构的形式赋值速度快,效率高,但是需要一定内存(宏定义),以空间换时间。

实现方式

宏定义函数实现数据队列的功能,适用不同数据结构,类似于 C++ 的模板方式,相同的实现逻辑,不同的数据结构。

点击查看代码

/**
* @brief 缓存区操作信息结构体定义
*/
typedef struct{
uint8_t state; /*!< 控制状态 */ uint8_t end; /*!< 循环队列尾哨兵 */ uint8_t head; /*!< 循环队列首哨兵 */ uint8_t num; /*!< 循环队列中能存储的最多组数 */
} QueueCtrl_t; #define QUEUE_ENABLE_COVER (0X80)
#define QUEUE_EXIT_DATA (0X01)
#define QUEUE_DATA_FULL (0X02)
#define QUEUE_DATA_LOCK (0X04) /**
* @brief 队列控制初始化
*
* @param[in,out] ctrl - 队列控制句柄
* @param[in] num - 队列数目大小
* @param[in] cover - 0,不覆盖; 1,队列满了覆盖顶端数据
*/
#define QUEUE_INIT(ctrl, maxNum, cover) ({\
ctrl.end = 0;\
ctrl.head = 0;\
ctrl.num = (maxNum);\
ctrl.state = 0x00;\
ctrl.state |= ((cover) ? QUEUE_ENABLE_COVER : 0);\
}) /**
* @brief 在队列末尾加入新的数据
*
* @param[in,out] dstLists - 队列缓存区
* @param[in] src - 新的数据
* @param[in,out] ctrl - 队列控制句柄
* @retval 返回的值含义如下
* @arg 0: 写入成功
* @arg -1: 写入失败
*/
#define QUEUE_PUSH_DATA(dstLists, src, ctrl) ({ \
int ret = 0;\
\
if (QUEUE_DATA_LOCK != ((ctrl.state) & QUEUE_DATA_LOCK)) \
{\
dstLists[(ctrl.end)++] = src;\
(ctrl.state) |= QUEUE_EXIT_DATA; \
\
if ((ctrl.end) >= (ctrl.num))\
{\
(ctrl.end) = 0;\
}\
\
if (((ctrl.state) & QUEUE_DATA_FULL) == QUEUE_DATA_FULL)\
{\
(ctrl.head) = (ctrl.end);\
}\
else if ((ctrl.end) == (ctrl.head))\
{\
(ctrl.state) |= QUEUE_DATA_FULL;\
\
if ((ctrl.state & QUEUE_ENABLE_COVER) != QUEUE_ENABLE_COVER) \
{\
(ctrl.state) |= QUEUE_DATA_LOCK;\
}\
}\
\
ret = 0;\
}\
else\
{\
ret = -1;\
}\
\
ret;\
}) /**
* @brief 在队列顶端读取数据
*
* @param[in,out] dstLists - 队列缓存区
* @param[out] dst - 读取的数据
* @param[in,out] ctrl - 队列控制句柄
* @retval 返回的值含义如下
* @arg 0: 读取成功
* @arg -1: 读取失败
*/
#define QUEUE_POP_DATA(dstLists, dst, ctrl) ({\
\
int ret = -1;\
\
if (((ctrl.state) & QUEUE_EXIT_DATA) == QUEUE_EXIT_DATA)\
{\
dst = dstLists[ctrl.head++];\
\
if ((ctrl.head) >= (ctrl.num))\
{\
ctrl.head = 0;\
}\
\
if ((ctrl.head) == (ctrl.end))\
{\
if (((ctrl.state) & QUEUE_DATA_FULL) != QUEUE_DATA_FULL)\
{\
(ctrl.state) &= ~QUEUE_EXIT_DATA;\
}\
}\
\
ret = 0;\
}\
\
(ctrl.state) &= ~QUEUE_DATA_LOCK;\
(ctrl.state) &= ~QUEUE_DATA_FULL;\
\
ret;\
})

Demo测试代码

最新文章

  1. Android selecter背景选择器使用
  2. POJ 1258 Agri-Net(最小生成树 Prim+Kruskal)
  3. Mysql利用mysql_multi配置一台主机多个实例(转)
  4. 向下滚动页面加载图片的js
  5. [HTML] CSS3 圆角
  6. Bing Map
  7. 多线程基础 (八)NSOperation相关
  8. jQuery中prop()函数控制多选框(全选,反选)
  9. 无法创建spool文件
  10. htop
  11. 【VC】VC工具栏图标合并工具(非tbcreator和visual toolbar)
  12. ios7新特性1-UI变化、UIKit动态行为支持与Text Kit新接口
  13. SVN经常使用命令说明
  14. [ios2] 利用钥匙串,在应用里保存用户密码的方法 【转】
  15. IBM Mq Spring JMS 的xml配置
  16. Attrib命令,可以让文件夹彻底的隐藏起来
  17. 【iOS】7.4 定位服务-&gt;3.4 地图框架MapKit 功能4:地图截图
  18. 4.vbs的循环,switch,判断等语句
  19. ThinkPHP5高阶实战教程
  20. VScode插件以及配置

热门文章

  1. &amp;#127822;
  2. 关于SpringBoot结合mybatis后遇到的坑
  3. Spring-Cloud-Alibaba之Seata
  4. 基于frida框架Hook native中的函数(1)
  5. Python 爬虫之urllib库的使用
  6. &lt;JVM下篇:性能监控与调优篇&gt;补充:使用OQL语言查询对象信息
  7. Day009 面向对象和方法回顾
  8. Idea一直卡在loading archetype list问题解决(或者报Unable to import maven project: See logs for details)
  9. Redis内存——内存消耗(内存都去哪了?)
  10. Docker 部署阿里云RocketMQ 4.5.1