当前位置: 首页 > news >正文

循环队列通用模版

循环队列:

RingQ.h

#ifndef RINGQ_H
#define RINGQ_H#include <stdint.h>
#include <stddef.h>
#include "stm32g4xx_hal.h"#ifndef RINGQ_DEFAULT_CAP
#define RINGQ_DEFAULT_CAP  (2048U)   // 默认 2KB
#endif// 可选:RTOS/中断临界区(按需在编译单元里重定义)
#ifndef RINGQ_ENTER_CRITICAL
#define RINGQ_ENTER_CRITICAL() __disable_irq()
#endif
#ifndef RINGQ_EXIT_CRITICAL
#define RINGQ_EXIT_CRITICAL() __enable_irq()
#endif#ifdef __cplusplus
extern "C" {
#endif// 基础循环队列核心(把它放进你自己的结构体即可)
typedef struct {uint8_t  *buf;           // 缓冲区uint32_t  cap;           // 容量(字节)volatile uint32_t head;  // 写索引 [0..cap-1]volatile uint32_t tail;  // 读索引 [0..cap-1]volatile uint32_t size;  // 已用字节数 [0..cap]
} RingQ;// ① 注册/初始化:绑定缓冲并清零
void     RingQ_Register(RingQ *q, void *buf, uint32_t cap);// ② 写入:把 src 的 len 字节写入队列;返回实际写入(空间不足则部分写入)
uint32_t RingQ_Write   (RingQ *q, const void *src, uint32_t len);// ③ 读取:从队列读最多 want_len 字节到 dst;返回实际读到的字节数
uint32_t RingQ_Read    (RingQ *q, void *dst, uint32_t want_len);// 便捷宏:静态声明一个队列与其缓冲,并提供 init
#define RINGQ_DECLARE(name, capacity)                                  \static uint8_t name##_buf[(capacity)];                              \static RingQ   name;                                                \static inline void name##_init(void){                               \RingQ_Register(&name, name##_buf, (capacity));                  \}#ifdef __cplusplus
}
#endif#endif // RINGQ_H

RingQ.c

#include "ringq.h"
#include <string.h>static inline uint32_t _min_u32(uint32_t a, uint32_t b){ return (a<b)?a:b; }void RingQ_Register(RingQ *q, void *buf, uint32_t cap){if (!q || !buf || cap == 0) return;q->buf  = (uint8_t*)buf;q->cap  = cap;q->head = 0;q->tail = 0;q->size = 0;
}uint32_t RingQ_Write(RingQ *q, const void *src_, uint32_t len){if (!q || !src_ || q->cap == 0 || len == 0) return 0;const uint8_t *src = (const uint8_t*)src_;RINGQ_ENTER_CRITICAL();uint32_t free = q->cap - q->size;uint32_t to_write = _min_u32(len, free);uint32_t widx = q->head;uint32_t first  = _min_u32(to_write, q->cap - widx);  // 尾部连续可写if (first) memcpy(&q->buf[widx], src, first);uint32_t second = to_write - first;                   // 环回到起始if (second) memcpy(&q->buf[0], src + first, second);q->head = (widx + to_write) % q->cap;q->size += to_write;RINGQ_EXIT_CRITICAL();return to_write;
}uint32_t RingQ_Read(RingQ *q, void *dst_, uint32_t want_len){if (!q || !dst_ || q->cap == 0 || want_len == 0) return 0;uint8_t *dst = (uint8_t*)dst_;RINGQ_ENTER_CRITICAL();uint32_t used = q->size;uint32_t to_read = _min_u32(want_len, used);uint32_t ridx = q->tail;uint32_t first  = _min_u32(to_read, q->cap - ridx);  // 尾部连续可读if (first) memcpy(dst, &q->buf[ridx], first);uint32_t second = to_read - first;                   // 环回到起始if (second) memcpy(dst + first, &q->buf[0], second);q->tail = (ridx + to_read) % q->cap;q->size -= to_read;RINGQ_EXIT_CRITICAL();return to_read;
}

注意!!!如果存在中断入队的情况记得加上开关中断,那么问题来了,如果不开关中断的话有没有办法不出错呢?

 

http://www.jsqmd.com/news/32506/

相关文章:

  • 如何选择一个人工智能项目
  • Flutter 开发文档
  • 别再只用S3了!RustFS的权限管理系统更安全?
  • STL初识project11
  • 告别漫长GC停顿:深入解析G1如何实现可预测的毫秒级响应
  • CSS 中 overflow 属性的两个分属性 overflow-x 和 overflow-y 互相影响问题
  • C#项目工程文件中,删除两头相同字符串,中间不一样的内容
  • Day13显示模式
  • 人工智能加持,海外市场无限可能!AI外呼助您轻松拓展全球业务!
  • 从编码到部署:5大AI工具盘活你的全栈开发流程
  • 如何是一个人工智能公司
  • 虚拟中间号和手机号有什么区别?
  • 关于OpenGL在AMD设备无法显示内容的解决方法
  • 超越代码补全:5个能理解你项目上下文的AI编程伙伴
  • 共绩算力 vscode git笔记
  • WPF 的ListBox 去除默认的Item项,鼠标hover的背景颜色
  • 不止高精度!正点原子 EL15 深度解析:精度、性价比全拉满!
  • 记录Oracle数据库账号异常锁定的排查处理过程
  • CF1770F Koxia and Sequence
  • 问题解决:gitlab-runner 报Jobs log exceeded limit of 4194304 bytes
  • 数据采集与融合技术实践2
  • NOIP 模拟赛 2 总结
  • 利用点击劫持漏洞触发XSS攻击:我是如何赚取350美元的
  • 人狗大战Ⅳ
  • 子类必须调用 super().__init__(page) 才能使用父类中的 self.page
  • 2025 年 11 月底盘悬挂减震气囊,空气弹簧减震气囊厂家最新推荐:产能、专利、环保三维数据透视
  • 2025 年板材源头厂家最新推荐排行榜:聚焦绿色生产与环保认证,精选七家优质企业深度解析
  • 2025年智能家居产品品牌推荐排行 top 5
  • 2025年智能家居产品品牌推荐排行:权威榜单与选择指南
  • 智能家居产品品牌怎么选择:2025年最新攻略