GD 32 环形队列

1.0 为什么要使用环形队列

在代码中使用环形队列进行程序的编写,由于在实际开发过程中,会出现接收数据频率太快快于主流程读取数据的频率,这个时候后面来的数据会覆盖前面一包数据,这个时候可以使用环形队列的方式解决这个问题。

2.0 环形队列的基本概念

队列是一种先进先出,后进后出的数据结构,队列有对头和队尾之分,对头负责出数据,队尾负责 数据的插入。

队列初始化与队列满的操作

使用环形队列的方式实现数据的重复使用

如何判断队列是空的还是满的,当对头指向队尾的时候,也就是对头和队尾同时指向一个数据区间重合的时候表示队列处于空的状态,当队列尾部 + 1,和头部重合的时候也表示队列处于满的状态


3.0 环形队列的实现

环形队列或循环队列是一种特殊的队列数据结构,它使用固定大小的数组实现,通过使用模运算来实现队尾到队首的循环链接。当队列达到数组的末端时,它可以回到数组的开始处继续存储数据,这样可以有效地避免数组空间的浪费。环形队列的两个关键指针是front(队首)和rear(队尾),它们分别指向队列的前端和后端。


代码实现:queue.c

#include <stdint.h>
#include "queue.h"

/**
****************************************************************
* @brief   初始化(创建)队列,每个队列须先执行该函数才能使用
* @param   queue, 队列变量指针
* @param   buffer, 队列缓存区地址
* @param   size, 队列缓存区长度
* @return 
****************************************************************
*/
void QueueInit(QueueType_t *queue, uint8_t *buffer, uint32_t size)
{
    queue->buffer = buffer;
    queue->size = size;
    queue->head = 0;
    queue->tail = 0;
}

/**
****************************************************************
* @brief   压入数据到队列中
* @param   queue, 队列变量指针
* @param   data, 待压入队列的数据
* @return  压入队列是否成功
****************************************************************
*/
QueueStatus_t QueuePush(QueueType_t *queue, uint8_t data)
{
    uint32_t index = (queue->tail + 1) % queue->size;

    if (index == queue->head)
    {
        return QUEUE_OVERLOAD;
    }
    queue->buffer[queue->tail] = data;
    queue->tail = index;
    return QUEUE_OK;
}

/**
****************************************************************
* @brief   从队列中弹出数据
* @param   queue, 队列变量指针
* @param   pdata, 待弹出队列的数据缓存地址
* @return  弹出队列是否成功
****************************************************************
*/
QueueStatus_t QueuePop(QueueType_t *queue, uint8_t *pdata)
{
    if(queue->head == queue->tail)
    {
        return QUEUE_EMPTY;
    }

    *pdata = queue->buffer[queue->head];
    queue->head = (queue->head + 1) % queue->size;
    return QUEUE_OK;
}

/**
****************************************************************
* @brief   压入一组数据到队列中
* @param   queue, 队列变量指针
* @param   pArray, 待压入队列的数组地址
* @param   len, 待压入队列的元素个数
* @return  实际压入到队列的元素个数
****************************************************************
*/
uint32_t QueuePushArray(QueueType_t *queue, uint8_t *pArray, uint32_t len)
{
    uint32_t i;
    for (i = 0; i < len; i++)
    {
        if(QueuePush(queue, pArray[i]) == QUEUE_OVERLOAD)
        {
            break;
        }
    }
    return i;
}

/**
****************************************************************
* @brief   从队列中弹出一组数据
* @param   queue, 队列变量指针
* @param   pArray, 待弹出队列的数据缓存地址
* @param   len, 待弹出队列的数据的最大长度
* @return  实际弹出数据的数量
****************************************************************
*/
uint32_t QueuePopArray(QueueType_t *queue, uint8_t *pArray, uint32_t len)
{
    uint32_t i;
    for(i = 0; i < len; i++)
    {
        if (QueuePop(queue, &pArray[i]) == QUEUE_EMPTY)
        {
            break;
        }
    }
    return i;
}

/**
****************************************************************
* @brief   获取队列中数据的个数
* @param   queue, 队列变量指针
* @return  队列中数据的个数
****************************************************************
*/
uint32_t QueueCount(QueueType_t *queue)
{
	if (queue->head <= queue->tail)
	{
		return queue->tail - queue->head;
	}
	
	return queue->size + queue->tail - queue->head;
}

代码实现queue.h

#ifndef  __QUEUE_H_
#define  __QUEUE_H_
#include <stdint.h>

#include <stdint.h>

typedef struct
{
    uint32_t head;        //数组下标,指向队头
    uint32_t tail;        //数组下标,指向队尾
    uint32_t size;        //队列缓存长度(初始化时赋值)
    uint8_t *buffer;      //队列缓存数组(初始化时赋值)
} QueueType_t;

typedef enum
{
	QUEUE_OK = 0,       //队列正常
	QUEUE_ERROR,        //队列错误
	QUEUE_OVERLOAD,     //队列已满
	QUEUE_EMPTY         //队列已空
} QueueStatus_t;

/**
****************************************************************
* @brief   初始化(创建)队列,每个队列须先执行该函数才能使用
* @param   queue, 队列变量指针
* @param   buffer, 队列缓存区地址
* @param   size, 队列缓存区长度
* @return 
****************************************************************
*/
void QueueInit(QueueType_t *queue, uint8_t *buffer, uint32_t size);

/**
****************************************************************
* @brief   压入数据到队列中
* @param   queue, 队列变量指针
* @param   data, 待压入队列的数据
* @return  压入队列是否成功
****************************************************************
*/
QueueStatus_t QueuePush(QueueType_t *queue, uint8_t data);

/**
****************************************************************
* @brief   从队列中弹出数据
* @param   queue, 队列变量指针
* @param   pdata, 待弹出队列的数据缓存地址
* @return  弹出队列是否成功
****************************************************************
*/
QueueStatus_t QueuePop(QueueType_t *queue, uint8_t *pdata);

/**
****************************************************************
* @brief   压入一组数据到队列中
* @param   queue, 队列变量指针
* @param   pArray, 待压入队列的数组地址
* @param   len, 待压入队列的元素个数
* @return  实际压入到队列的元素个数
****************************************************************
*/
uint32_t QueuePushArray(QueueType_t *queue, uint8_t *pArray, uint32_t len);

/**
****************************************************************
* @brief   从队列中弹出一组数据
* @param   queue, 队列变量指针
* @param   pArray, 待弹出队列的数据缓存地址
* @param   len, 待弹出队列的数据的最大长度
* @return  实际弹出数据的数量
****************************************************************
*/
uint32_t QueuePopArray(QueueType_t *queue, uint8_t *pArray, uint32_t len);

/**
****************************************************************
* @brief   获取队列中数据的个数
* @param   queue, 队列变量指针
* @return  队列中数据的个数
****************************************************************
*/
uint32_t QueueCount(QueueType_t *queue);


#endif

以上是环形队列实现的基础代码,参考郭天祥ARM32教程编写,仅用于学习参考

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于 GD32 平台上使用 FreeRTOS 的消息队列,您可以通过以下步骤进行操作: 1. 创建消息队列:使用 `xQueueCreate()` 函数创建一个消息队列对象。该函数的参数包括队列的长度和每个消息的大小。例如,要创建一个长度为 10,每个消息大小为 4 字节的消息队列,可以使用以下代码: ```c QueueHandle_t xQueue = xQueueCreate(10, sizeof(uint32_t)); ``` 2. 发送消息到队列:使用 `xQueueSend()` 函数将消息发送到队列中。该函数的参数包括队列句柄、要发送的消息以及等待时间。如果队列已满,可以选择等待一段时间或者立即返回。以下是一个示例代码: ```c uint32_t data = 123; BaseType_t xStatus = xQueueSend(xQueue, &data, portMAX_DELAY); if (xStatus != pdPASS) { // 消息发送失败 } ``` 3. 接收消息:使用 `xQueueReceive()` 函数从队列中接收消息。该函数的参数包括队列句柄、接收缓冲区以及等待时间。如果队列为空,可以选择等待一段时间或者立即返回。以下是一个示例代码: ```c uint32_t receivedData; BaseType_t xStatus = xQueueReceive(xQueue, &receivedData, portMAX_DELAY); if (xStatus == pdPASS) { // 成功接收到消息 } else { // 消息接收失败 } ``` 需要注意的是,以上代码仅为示例,您可以根据具体需求进行修改。另外,还有其他一些与消息队列相关的函数可以使用,例如 `uxQueueMessagesWaiting()` 可以获取队列中待处理的消息数量。 希望以上信息对您有所帮助!如果您有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值