循环队列存储

Queue.c

/**
 ******************************************************************************
 * @文件名 	Queue.c
 * @作者	  Jing
 * @版本	  V01
 * @日期	  2023-08-09
 * @作用	
 ******************************************************************************
 * 修改记录:
 * 日期           修改者          修改内容
 * 2023-08-09	     Jing    		     初版
 ******************************************************************************
 * @注意
 *
 * Copyright (C) 2023-2025
 * All rights reserved Jing
 *
 ******************************************************************************/
 
#include "queue.h"
#include <string.h>
#include "usart.h"
#include "gpio.h"

DataPacket receiveQueue[MAX_QUEUE_SIZE]; // 接收队列
int front = 0;                           // 队头指针
int rear = 0;                            // 队尾指针

/*
**********************************************************************************
* 函数名: Enqueue
* 功  能: 数据进入队列
* 形  参: data,len
* 返回值: 无
**********************************************************************************
*/
void Enqueue(uint8_t *data, uint8_t len) 
{
    if (IsQueueFull()) 
    {
        // 队列已满,丢弃最旧的数据
        front = (front + 1) % MAX_QUEUE_SIZE;
    }

    memcpy(receiveQueue[rear].data, data, len);  //获取数据内容
    receiveQueue[rear].len = len;                //获取数据长度
    rear = (rear + 1) % MAX_QUEUE_SIZE;          //更新队尾指针
		//HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);     //测试使用
}

/*
**********************************************************************************
* 函数名: Dequeue
* 功  能: 队列提取数据
* 形  参: data
* 返回值: 无
**********************************************************************************
*/
int Dequeue(uint8_t *data) 
{
    if (IsQueueEmpty()) 
    {
        // 队列为空,没有数据可出队
        return 0;
    }

    memcpy(data, receiveQueue[front].data, receiveQueue[front].len);  //取出数据内容
    int len = receiveQueue[front].len;                                //获取数据长度
    front = (front + 1) % MAX_QUEUE_SIZE;                             //更新队首指针
    return len;                                                       //返回数据长度值
}

/*
**********************************************************************************
* 函数名: IsQueueEmpty
* 功  能: 判断队列是否为空
* 形  参: 无
* 返回值: 0、1
**********************************************************************************
*/
int IsQueueEmpty(void)
{
    return (front == rear);
}

/*
**********************************************************************************
* 函数名: IsQueueFull
* 功  能: 判断队列是否为满
* 形  参: 无
* 返回值: 0、1
**********************************************************************************
*/
int IsQueueFull(void)
{
    return ((rear + 1) % MAX_QUEUE_SIZE == front);
}

/*
**********************************************************************************
* 函数名: ClearQueue
* 功  能: 清空队列、初始化队列
* 形  参: 无
* 返回值: 无
**********************************************************************************
*/
void ClearQueue(void)
{
    front = 0;
    rear = 0;
}

Queue.h

/**
 ******************************************************************************
 * @文件名 	Queue.h
 * @作者	  Jing
 * @版本	  V01
 * @日期	  2023-08-09
 * @作用	
 ******************************************************************************
 * 修改记录:
 * 日期           修改者          修改内容
 * 2023-08-09	     Jing    		     初版
 ******************************************************************************
 * @注意
 *
 * Copyright (C) 2023-2025
 * All rights reserved Jing
 *
 ******************************************************************************/
 
#ifndef QUEUE_H
#define QUEUE_H

#include <stdint.h>

#define MAX_QUEUE_SIZE 256 // 接收队列最大容量
#define BUFFER_SIZE 100    // 数据包最大长度

typedef struct {
    uint8_t data[BUFFER_SIZE];
    uint8_t len;
} DataPacket;

void Enqueue(uint8_t *data, uint8_t len);
int  Dequeue(uint8_t *data);
int  IsQueueEmpty(void);
int  IsQueueFull(void);
void ClearQueue(void);

#endif

主函数:

uint8_t receive_data[BUFFER_SIZE];
int main(void)
{
  
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_UART5_Init();
  MX_USART3_UART_Init();
  ClearQueue();

  while (1)
  {	
	// 从接收队列中取出数据并进行处理    
    int len = Dequeue(receive_data);
    if (len > 0) 
	{
		HAL_UART_Transmit_DMA(&huart3,receive_data,len);
    }			
  }
}

简要说明:

在循环队列的实现中,每个位置上并不链接一个数组,而是一个指向DataPacket结构体的指针。每个指针指向一个动态分配的DataPacket结构体,该结构体包含数据内容和长度。

具体来说,入队函数会进行以下操作:

  1. 动态分配内存以创建一个新的DataPacket结构体。
  2. 将数据复制到新创建的DataPacket结构体中,并将数据长度保存在结构体的len字段中。
  3. 将指向新创建的DataPacket结构体的指针存储到队列中(即存储到receiveQueue数组中)。
  4. 更新队列的尾部指针(rear)。

出队函数会进行以下操作:

  1. 获取队列首部位置(front)上的DataPacket结构体指针。
  2. DataPacket结构体中获取数据内容和长度。
  3. 释放DataPacket结构体所占用的内存。
  4. 更新队列的首部指针(front)。

总结起来,在循环队列的实现中,每个位置上并不直接链接一个数组,而是存储一个指向DataPacket结构体的指针。通过动态分配内存,可以为每个数据包创建独立的结构体,并在结构体中保存数据内容和长度。同时,通过更新队列的尾部指针和首部指针来实现入队和出队操作。

压力测试:

定时30ms发送12字节数据,半小时测试未出现丢帧情况(缺少1帧因为关闭串口时,数据帧已发送但未来得及接收)

 

2.0版本

/**
 ******************************************************************************
 * @文件名 	  Queue.c
 * @作者	  Jing
 * @版本	  V01
 * @日期	  2023-08-11
 * @作用	
 ******************************************************************************
 * 修改记录:
 * 日期           修改者          修改内容
 * 2023-08-11	  Jing            2.0版
 ******************************************************************************
 * @注意
 *
 * Copyright (C) 2023-2025
 * All rights reserved Jing
 *
 ******************************************************************************/
 
#include "queue.h"
#include <string.h>
#include "usart.h"
#include "gpio.h"

DataPacket receiveQueues[NUM_QUEUES][MAX_QUEUE_SIZE]; // 多个队列的数据存储数组
int front[NUM_QUEUES] = {0};                          // 多个队列的队头指针
int rear[NUM_QUEUES] = {0};                           // 多个队列的队尾指针

void Enqueue(uint8_t *data, uint8_t len, QueueFunction function) 
{
    int queueIndex = (int)function;
  
    if (IsQueueFull(function)) 
    {
        // 队列已满,丢弃最旧的数据
        front[queueIndex] = (front[queueIndex] + 1) % MAX_QUEUE_SIZE;
    }

    memcpy(receiveQueues[queueIndex][rear[queueIndex]].data, data, len);  //获取数据内容
    receiveQueues[queueIndex][rear[queueIndex]].len = len;                //获取数据长度
    rear[queueIndex] = (rear[queueIndex] + 1) % MAX_QUEUE_SIZE;           //更新队尾指针
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);                                //测试使用
}

int Dequeue(uint8_t *data, QueueFunction function) 
{
    int queueIndex = (int)function;
  
    if (IsQueueEmpty(function)) 
    {
        // 队列为空,没有数据可出队
        return 0;
    }

    memcpy(data, receiveQueues[queueIndex][front[queueIndex]].data, receiveQueues[queueIndex][front[queueIndex]].len); //取出数据内容
    int len = receiveQueues[queueIndex][front[queueIndex]].len;                                                        //获取数据长度
    front[queueIndex] = (front[queueIndex] + 1) % MAX_QUEUE_SIZE;                                                      //更新队首指针
    return len;                                                                                                        //返回数据长度值
}

int IsQueueEmpty(QueueFunction function)
{
    int queueIndex = (int)function;
    return (front[queueIndex] == rear[queueIndex]);
}

int IsQueueFull(QueueFunction function)
{
    int queueIndex = (int)function;
    return ((rear[queueIndex] + 1) % MAX_QUEUE_SIZE == front[queueIndex]);
}

void ClearQueue(QueueFunction function)
{
    int queueIndex = (int)function;
    front[queueIndex] = 0;
    rear[queueIndex] = 0;
}

void QueueInit(void)
{
    int i;
    for (i = 0; i < NUM_QUEUES; i++)
    {
        ClearQueue((QueueFunction)i);
    }
}







/**
 ******************************************************************************
 * @文件名 	  Queue.h
 * @作者	  Jing
 * @版本	  V01
 * @日期	  2023-08-11
 * @作用	
 ******************************************************************************
 * 修改记录:
 * 日期           修改者          修改内容
 * 2023-08-11	   Jing    		   2.0版
 ******************************************************************************
 * @注意
 *
 * Copyright (C) 2023-2025
 * All rights reserved Jing
 *
 ******************************************************************************/
 
#ifndef QUEUE_H
#define QUEUE_H

#include <stdint.h>

#define MAX_QUEUE_SIZE 256 // 单个队列最大容量
#define BUFFER_SIZE 50    // 数据包最大长度
#define NUM_QUEUES 2      // 队列数量

typedef struct {
    uint8_t data[BUFFER_SIZE];
    uint8_t len;
} DataPacket;

typedef enum {
    UART5_DMA_RECEIVE,
    UART5_DMA_TRANSMIT
} QueueFunction;

void Enqueue(uint8_t *data, uint8_t len, QueueFunction function);
int  Dequeue(uint8_t *data, QueueFunction function);
int  IsQueueEmpty(QueueFunction function);
int  IsQueueFull(QueueFunction function);
void ClearQueue(QueueFunction function);
void QueueInit(void);

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值