北屋教程网

专注编程知识分享,从入门到精通的编程学习平台

通用队列管理模块设计 —— 简洁高效的嵌入式数据调度核心

在嵌入式系统中,任务之间常常需要通过一种结构化方式传递消息或数据,例如传感器采集值上传、串口数据解析、指令调度、事件响应等。在这些场景下,“队列(Queue)”是一种非常经典且高效的数据组织形式。

通用队列模块以结构体数组为核心,结合固定内存与循环索引,实现了一个轻量、稳定、适配性强的队列管理器。该模块适合用于裸机或 RTOS 系统,是构建通信缓冲、消息队列、任务分发机制的基础组件。


核心结构与概念

队列管理器 queue_t

队列通过 queue_t 结构体进行管理,内部维护以下成员:

  • base:队列内存起始地址;
  • size:队列最大容量(元素个数);
  • element_size:每个元素的字节数;
  • front、rear:队头与队尾索引,用于控制循环进出。

队列结构采用 循环数组,即环形缓冲的方式,避免频繁移动内存,入队出队仅需更新索引。


功能概览

接口函数

功能描述

queue_create

创建并初始化队列

queue_is_empty

判断队列是否为空

queue_is_full

判断队列是否已满

queue_put

入队(添加元素)

queue_get

出队(移除元素)

queue_peek

预读取队头元素,不出队

queue_del

删除队头元素,不读取

queue_size

获取当前队列长度

queue_clr

清空队列

一、模块功能概述

本队列模块支持以下基础能力:

  • 队列的初始化与创建;
  • 判断队列空满状态;
  • 元素入队与出队;
  • 队列长度查询;
  • 队列内容预读取(不出队);
  • 队列清空;
  • 队尾元素删除。

该队列采用循环数组结构,不依赖动态内存分配,适合资源受限的嵌入式环境使用。支持自定义元素类型,通过配置元素大小与容器地址实现通用性管理。

二、使用方式简述

使用者在使用该模块时需自行提供以下参数:

  • 数据缓冲区指针;
  • 缓冲区容量(元素个数);
  • 单个元素的大小(字节);
  • 队列管理结构体实例。

通过调用创建函数对队列进行初始化后,即可使用相关接口进行操作,如入队出队等。

三、接口功能说明

1. 创建队列

通过 queue_create 函数传入结构体、容器地址、容器容量、元素大小,即可完成队列初始化。

2. 状态判断

提供 queue_is_empty 和 queue_is_full 接口判断当前队列状态,便于进行边界处理。

3. 元素操作

  • 使用 queue_put 向队列尾部写入一个元素;
  • 使用 queue_get 从队列头部读取一个元素并出队;
  • 使用 queue_peek 可在不出队的情况下获取队头元素地址;
  • 使用 queue_del 可直接丢弃队头元素(删除而不读取);
  • 使用 queue_clr 可清空整个队列内容;
  • 使用 queue_size 可获取当前队列中元素数量。

1. 串口接收命令缓存

串口中断接收到数据帧后,将帧内容通过 queue_put 入队,主循环中调用 queue_get 提取完整指令进行解析,避免数据丢失或阻塞。

typedef struct {
    uint8_t data[8];
} uart_cmd_t;

uart_cmd_t cmd_buf[16];
queue_t cmd_queue;

queue_create(&cmd_queue, cmd_buf, 16, sizeof(uart_cmd_t));

2. 多任务消息传递(RTOS环境)

任务 A 收集数据并通过 queue_put 入队,任务 B 轮询或通过事件驱动使用 queue_get 获取消息,完成跨任务通信。

3. 简易任务调度器

使用 queue_t 管理一个“函数指针 + 参数”结构体列表,即可构建轻量的调度任务表,实现软中断调度或定时任务执行。

通用队列管理模块,是构建嵌入式通信、缓存和调度功能的坚实基础。通过灵活封装与高效实现,该模块能够帮助开发者快速构建稳定的数据流通路。在系统架构设计中,清晰的数据组织方式往往是高质量代码的关键,队列,正是连接数据与逻辑的桥梁。

开源代码:

#include "queue.h"
#include <stddef.h>
#include <string.h>

/* @brief      创建一个队列
 * @param[in]  q    - 队列管理器
 * @param[in]  base - 队列容器基地址
 * @param[in]  size - 队列容器可容纳元素个数
 * @param[in]  element_size - 队列元素大小(sizeof(type))
 * @return     true - 创建成功, false - 创建失败
 */
bool queue_create(queue_t *q, void *base, int size, int element_size)
{
    if (q == NULL || base == NULL || size== 0 || element_size == 0)
        return false;
    q->base         = base;
    q->size         = size;
    q->element_size = element_size;
    q->front        = q->rear = 0;
    return true;
}


/* @brief      判断队列是否为空
 * @return    true - 队列为空, false - 队列非空
 */
bool queue_is_empty(queue_t *q)
{
    return q->front == q->rear;
}

/* @brief      判断队列是否满
 * @return     true - 队列非满, false - 队列未满
 */
bool queue_is_full(queue_t *q)
{
    return (q->rear + 1) % q->size == q->front;
}

/* @brief      入队(添加元素至队尾)
 * @param[in]  element  - 队列元素
 * @return     true - 成功入队, false - 队列满
 */
bool queue_put(queue_t *q,  void *element)
{
    if (queue_is_full(q))
        return false;
    memcpy((unsigned char *)q->base + q->rear * q->element_size, element, 
           q->element_size);
    q->rear = (q->rear + 1) % q->size;
    return true;
}

/* @brief      出队(移除队首元素)
 * @param[in]  element  - 指向队首元素的地址
 * @return     true - 成功出队, false - 队列为空
 */
bool queue_get(queue_t *q,  void *element)
{
    if (queue_is_empty(q))
        return false;   
    memcpy(element, (unsigned char *)q->base + q->front * q->element_size,
          q->element_size);
    q->front = (q->front + 1) % q->size;
    return true;
}

/* @brief      获取队首元素地址(预读取)
 * @param[in]  element  - 指向队首元素的地址
 * @return     true - 获取成功, false - 获取失败队列为空
 */
bool queue_peek(queue_t *q, void **element)
{
    if (queue_is_empty(q))
        return false;   
    *element = (void *)((unsigned char *)q->base + q->front * 
              q->element_size);
    return true;
}

/* @brief      删除队尾元素
 * @return     true - 成功移除, false -  队列为空, 
 */
bool queue_del(queue_t *q)
{
    if (queue_is_empty(q))
        return false;   
    q->front = (q->front + 1) % q->size;
    return true;
}

/* @brief      获取队列元素个数
 * @return    队列元素个数
 */
int queue_size(queue_t *q)
{
    return (q->rear + q->size - q->front ) % q->size;
}

/* @brief      清空队列
 * @return    none
 */
void queue_clr(queue_t *q)
{
    q->front = q->rear = 0;
}
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言