Last active
February 20, 2025 08:36
-
-
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`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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