Skip to content

Instantly share code, notes, and snippets.

@wsxq2
Last active February 20, 2025 08:36
Show Gist options
  • Save wsxq2/9a138c111beb7b5cd253b0fe8c42e083 to your computer and use it in GitHub Desktop.
Save wsxq2/9a138c111beb7b5cd253b0fe8c42e083 to your computer and use it in GitHub Desktop.
STM32简单环形队列实现,有两种策略:未定义`Q_KEEP_NEWEST`时会在队列满时无法入队列,即丢弃最新的帧;定义`Q_KEEP_NEWEST`时在队列满时也会成功入队列,并删除最旧的元素,从而保证最新的帧总能接收。使用前根据具体使用需求调整`Q_MSG_BUF_LEN`和`Q_MSG_MAX_SIZE`
#include "queue.h"
#include <stdio.h>
#include <string.h>
bool q_create(q_queue* q, int maxsize)
{
if (maxsize > Q_MSG_MAX_SIZE)
return false;
q->front = 0;
q->rear = 0;
q->maxsize = maxsize;
return true;
}
void q_print_msg(const q_message* msg)
{
_dbg_printf("flag: %d, len: %d, msg: ", msg->flag, msg->len);
#if 1
for (int i = 0; i < msg->len; i++) {
_dbg_printf("%02x ", msg->buf[i]);
}
#else
_dbg_printf("%s", msg->buf);
#endif
_dbg_printf("\n");
}
void q_traverse(const q_queue* q)
{
int i = q->front;
_dbg_printf("q->front: %d, q->rear: %d, q->maxsize: %d, msg: \n", q->front, q->rear, q->maxsize);
while (i % q->maxsize != q->rear) {
q_print_msg(&q->msg[i]);
i++;
}
_dbg_printf("\n");
}
bool q_empty(const q_queue* q)
{
return q->front == q->rear;
}
bool q_full(const q_queue* q)
{
return q->front == ((q->rear + 1) % q->maxsize);
}
bool q_enqueue(q_queue* q, const q_message* val)
{
#ifndef Q_KEEP_NEWEST
if(q_full(q)) {
return false;
}
#endif
if (val->len > Q_MSG_BUF_LEN) {
return false;
}
q->msg[q->rear].flag = val->flag;
q->msg[q->rear].len = val->len;
memcpy(q->msg[q->rear].buf, val->buf, val->len);
#ifdef Q_KEEP_NEWEST
if(q_full(q)) {
q->front = (q->front + 1) % q->maxsize;
}
#endif
q->rear = (q->rear + 1) % q->maxsize;
return true;
}
bool q_dequeue(q_queue* q, q_message* val)
{
if (q_empty(q)) {
return false;
} else {
*val = q->msg[q->front];
q->front = (q->front + 1) % q->maxsize;
return true;
}
}
int q_size(q_queue* q)
{
return (q->rear + q->maxsize - q->front) % q->maxsize;
}
#ifdef Q_UNIT_TEST
#include <assert.h>
int main(int argc, char *argv[])
{
bool ret;
q_queue q;
ret = q_create(&q, Q_MSG_MAX_SIZE);
assert(ret == true);
q_message msg={0};
q_enqueue(&q, &(q_message){0,3,{'a','b','c'}});
ret = q_enqueue(&q, &(q_message){1,2,{'a','b'}});
assert(ret == true);
ret = q_enqueue(&q, &(q_message){2,2,{'a','b'}});
assert(ret == true);
ret=q_enqueue(&q, &(q_message){3,2,{'a','b'}});
#ifdef Q_KEEP_NEWEST
assert(ret == true);
#else
assert(ret == false);
#endif
q_traverse(&q);
q_dequeue(&q, &msg);
q_print_msg(&msg);
q_dequeue(&q, &msg);
ret = q_dequeue(&q, &msg);
assert(ret == true);
ret = q_dequeue(&q, &msg);
assert(ret == false);
return 0;
}
#endif
#ifndef QUEUE_ARQIO_H
#define QUEUE_ARQIO_H
#include <stdbool.h>
#include <stdint.h>
#define Q_KEEP_NEWEST //allow new message enqueue when queue is full
#define Q_MSG_BUF_LEN 255 //max msg buf len, if need, change it
#define Q_MSG_MAX_SIZE 4 //max message size, if need, change it. if this is 4, then queue can only have 3 messages
typedef struct {
uint8_t flag; //reserved for special usage, user choose whether use this
uint16_t len; //buf actual len
uint8_t buf[Q_MSG_BUF_LEN]; //buffer, usually used for cache frame
} q_message; //queue member
typedef struct {
q_message msg[Q_MSG_MAX_SIZE];
int front;
int rear;
int maxsize; //can't exceed Q_MSG_MAX_SIZE
} q_queue;
bool q_create(q_queue* q, int maxsize);
void q_print_msg(const q_message* msg);
void q_traverse(const q_queue* q);
bool q_empty(const q_queue* q);
bool q_full(const q_queue* q);
bool q_enqueue(q_queue* q, const q_message* val);
bool q_dequeue(q_queue* q, q_message* val);
int q_size(q_queue* q);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment