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

环形缓冲区(Ring Buffer)

文章目录1. 环形缓冲区工作流程2. C 语言实现2.1 头文件 ringbuf.hRINGBUF_SIZE2562.2 源文件 ringbuf.c3. 在串口中断服务函数中使用示例4. 临界区保护说明5. 总结1. 环形缓冲区工作流程写入流程 (ISR中调用)写入流程 (ISR中调用)未满已满接收中断触发读取数据寄存器缓冲区是否满?写入数据到 head 位置head (head 1) % BUFFER_SIZE返回可选: 覆盖/丢弃记录溢出标志读取流程 (主循环/任务)读取流程 (主循环/任务)非空空应用需要读取数据缓冲区是否空?从 tail 位置读取数据tail (tail 1) % BUFFER_SIZE返回读取的字节返回 0 或错误码缓冲区逻辑head指向下一个可写入位置。tail指向下一个可读取位置。当head tail时缓冲区为空。当(head 1) % size tail时缓冲区为满保留一个字节用于区分空/满。2. C 语言实现2.1 头文件 ringbuf.hRINGBUF_SIZE256#ifndefRINGBUF_H#defineRINGBUF_H#includestdint.h#includestdbool.h/* 缓冲区大小需为 2 的幂时可用位掩码优化这里用通用取模方式 */#defineRINGBUF_SIZE256/* 环形缓冲区控制结构 */typedefstruct{uint8_tbuffer[RINGBUF_SIZE];/* 数据存储区 */volatileuint32_thead;/* 写指针ISR 修改 */volatileuint32_ttail;/* 读指针主循环修改 */volatileuint32_toverflow_cnt;/* 溢出计数器 */}ringbuf_t;/* 初始化 */voidringbuf_init(ringbuf_t*rb);/* 写入一个字节通常在中断中调用 */boolringbuf_put(ringbuf_t*rb,uint8_tdata);/* 读取一个字节非阻塞返回实际读取字节数 */intringbuf_get(ringbuf_t*rb,uint8_t*data);/* 读取多个字节 */uint32_tringbuf_read(ringbuf_t*rb,uint8_t*out,uint32_tmax_len);/* 获取当前可读字节数 */uint32_tringbuf_available(constringbuf_t*rb);/* 获取空闲空间大小 */uint32_tringbuf_free_space(constringbuf_t*rb);/* 清空缓冲区 */voidringbuf_clear(ringbuf_t*rb);/* 检查是否为空 */boolringbuf_is_empty(constringbuf_t*rb);/* 检查是否为满 */boolringbuf_is_full(constringbuf_t*rb);/* 获取溢出次数 */uint32_tringbuf_get_overflow(ringbuf_t*rb);#endif/* RINGBUF_H */2.2 源文件 ringbuf.c#includeringbuf.h/* 初始化缓冲区 */voidringbuf_init(ringbuf_t*rb){rb-head0;rb-tail0;rb-overflow_cnt0;}/* 检查是否为空 */boolringbuf_is_empty(constringbuf_t*rb){return(rb-headrb-tail);}/* 检查是否为满保留一个字节 */boolringbuf_is_full(constringbuf_t*rb){return(((rb-head1)%RINGBUF_SIZE)rb-tail);}/* 获取可读字节数 */uint32_tringbuf_available(constringbuf_t*rb){/* 注意head 和 tail 都是 volatile需整体读取一次 */uint32_thrb-head;uint32_ttrb-tail;if(ht){returnh-t;}else{returnRINGBUF_SIZE-th;}}/* 获取空闲空间大小 */uint32_tringbuf_free_space(constringbuf_t*rb){returnRINGBUF_SIZE-1-ringbuf_available(rb);}/* 写入一个字节中断安全但若中断嵌套需临界区保护 */boolringbuf_put(ringbuf_t*rb,uint8_tdata){if(ringbuf_is_full(rb)){rb-overflow_cnt;returnfalse;/* 缓冲区满写入失败 */}rb-buffer[rb-head]data;/* 写指针递增需确保操作原子性部分架构需关中断 */rb-head(rb-head1)%RINGBUF_SIZE;returntrue;}/* 读取一个字节返回实际读取字节数0 或 1 */intringbuf_get(ringbuf_t*rb,uint8_t*data){if(ringbuf_is_empty(rb)){return0;}*datarb-buffer[rb-tail];rb-tail(rb-tail1)%RINGBUF_SIZE;return1;}/* 批量读取数据 */uint32_tringbuf_read(ringbuf_t*rb,uint8_t*out,uint32_tmax_len){uint32_tavailringbuf_available(rb);uint32_tread_len(max_lenavail)?max_len:avail;uint32_ti;for(i0;iread_len;i){/* 此处未使用 ringbuf_get 以避免重复计算可用长度 */out[i]rb-buffer[rb-tail];rb-tail(rb-tail1)%RINGBUF_SIZE;}returnread_len;}/* 清空缓冲区 */voidringbuf_clear(ringbuf_t*rb){/* 为保证中断安全应先关中断 */rb-tailrb-head;}/* 获取溢出次数 */uint32_tringbuf_get_overflow(ringbuf_t*rb){returnrb-overflow_cnt;}3. 在串口中断服务函数中使用示例以下展示如何将环形缓冲区集成到 USART 接收中断中以 STM32 HAL 为例原理通用。#includeringbuf.h#includestm32f1xx_hal.h/* 全局环形缓冲区实例 */ringbuf_tuart_rx_ringbuf;/* 初始化 */voiduart_init(void){ringbuf_init(uart_rx_ringbuf);// ... 配置 USART 并使能接收中断 ...HAL_UART_Receive_IT(huart1,rx_byte,1);}/* 接收中断回调HAL 库方式 */voidHAL_UART_RxCpltCallback(UART_HandleTypeDef*huart){if(huart-InstanceUSART1){uint8_tdatahuart-Instance-DR;/* 读取数据寄存器 */ringbuf_put(uart_rx_ringbuf,data);/* 存入环形缓冲区 */HAL_UART_Receive_IT(huart1,rx_byte,1);/* 重新开启中断 */}}/* 主循环中读取数据 */voidmain_loop(void){uint8_tbuf[64];uint32_tlen;while(1){lenringbuf_read(uart_rx_ringbuf,buf,sizeof(buf));if(len0){/* 处理收到的数据 */process_data(buf,len);}// ... 其他任务 ...}}4. 临界区保护说明在中断与主循环共享head和tail时以下操作需注意原子性写操作head递增前可能被中断打断若中断也写缓冲区会导致数据覆盖。解决方案在修改head前关中断修改后恢复或在单写单读且指针为整型时利用天然原子性但依赖架构。读操作tail的修改可能被中断读取到不一致的中间状态。解决方案在ringbuf_read循环中如果担心中断干扰可在读head和tail时关中断或使用内存屏障。简单示例以 ARM Cortex-M 为例boolringbuf_put_safe(ringbuf_t*rb,uint8_tdata){bool ret;__disable_irq();retringbuf_put(rb,data);__enable_irq();returnret;}5. 总结使用环形缓冲区能有效缓冲串口突发数据避免丢失。代码采用“保留一个字节”的方式区分空/满逻辑清晰。流程图直观展示写入和读取的决策流程。实际工程中需根据平台增加临界区保护。若需支持动态大小或使用 2 的幂次方大小以位运算加速可进一步优化。

相关文章:

环形缓冲区(Ring Buffer)

文章目录1. 环形缓冲区工作流程2. C 语言实现2.1 头文件 ringbuf.h(RINGBUF_SIZE256)2.2 源文件 ringbuf.c3. 在串口中断服务函数中使用示例4. 临界区保护说明5. 总结1. 环形缓冲区工作流程 写入流程 (ISR中调用): #mermaid-svg-j444GbsyedL…...

新鲜出炉!2026 Agent智能体平台推荐排行 办公/营销/研发全场景适配

一、摘要据IDC发布的《中国模型即服务(MaaS)及AI大模型解决方案市场追踪,2024H2》报告显示,国内Agent智能体平台市场规模年增速达68%,但市场上产品同质化严重,仅32%的产品能真正适配多行业全场景需求&#…...

DFRobot_BMP280库深度解析:嵌入式BMP280传感器驱动开发指南

1. DFRobot_BMP280库深度解析:面向嵌入式工程师的BMP280传感器驱动开发指南BMP280是博世(Bosch)推出的高精度数字环境传感器,集成温度、气压测量功能,并支持基于气压反推海拔高度。DFRobot为其SEN0372模块开发的DFRobo…...

MetalLB才是给Ingress这个老登做负重前行的那个男人肚

一、核心问题及解决方案(按踩坑频率排序) 问题 1:误删他人持有锁——最基础也最易犯的漏洞 成因:释放锁时未做身份校验,直接执行 DEL 命令删除键。典型场景:服务 A 持有锁后,业务逻辑耗时超过锁…...

BM2102-9x-1 Sub-1G OOK无线发射模块驱动与工程实践

1. 项目概述BM2102-9x-1 是由 Best Modules 推出的一款工作于 Sub-1G 频段(典型频点为 315MHz、433.92MHz、868MHz 和 915MHz)的 OOK(On-Off Keying)无线发射模块,采用透明传输(Transparent Transmission&a…...

Laravel 多关键词跨字段模糊搜索的优化实现方案.txt

权限、链路层类型、pcapng格式、HTTP流重组是gopacket抓包四大易错点:Linux需cap_net_raw权限,macOS需动态查接口;gopacket不支持pcapng;默认不解析分片/TLS/HTTP流;LinkType必须从handle获取而非硬编码。pcap.OpenLiv…...

Win11家庭版无Hyper-V?手把手教你安装WSL2并迁移Ubuntu-24.04

1. Win11家庭版为什么没有Hyper-V? 很多朋友升级到Win11家庭版后,发现系统里找不到Hyper-V功能。这其实是因为微软在系统版本功能上做了区分:Hyper-V作为企业级虚拟化技术,默认只包含在专业版、企业版和教育版中。家庭版用户想要使…...

算法备案不是终点,而是起点:AI原生软件全生命周期合规治理框架,覆盖需求→上线→迭代→下线4阶段

第一章:算法备案不是终点,而是起点:AI原生软件全生命周期合规治理框架,覆盖需求→上线→迭代→下线4阶段 2026奇点智能技术大会(https://ml-summit.org) 算法备案仅是监管合规的法定入口,而非治理闭环的完成标志。真…...

全球线性可变位移传感器:工业数字化转型与智能制造驱动下的稳增进阶,2025年11.7亿,2032年规模19.25亿,2026-2032年CAGR7.5%

QYResearch调研显示,2025年全球线性可变位移传感器市场规模大约为11.7亿美元,预计2032年将达到19.25亿美元,2026-2032期间年复合增长率(CAGR)为7.5%。技术创新驱动市场发展制造商正专注于提升LVDT传感器的性能特征&…...

SQL如何利用JOIN优化查询复杂的多维度指标_预索引关联键

WHERE条件放错位置会导致预索引失效,因优化器被迫全量JOIN后再过滤;应将关联表筛选条件移至ON子句或建立(status,id)复合索引,并用EXPLAIN验证索引使用。JOIN 时为什么 WHERE 条件放错位置会让预索引失效MySQL 或 PostgreSQL 中,J…...

大模型驱动研发的度量革命:1套可落地的MLOps+DevOps融合指标矩阵(含开源Schema v2.3)

第一章:AI原生软件研发度量指标体系设计 2026奇点智能技术大会(https://ml-summit.org) AI原生软件的研发范式已显著区别于传统软件工程——模型即逻辑、数据即契约、反馈即验证。其度量体系需同时覆盖模型生命周期(训练、推理、监控)、代码…...

Laravel Redis 缓存多存储隔离与精准清理方案

Laravel 中若为多个缓存 store 配置相同 Redis 连接,调用 cache:clear 或 store()->clear() 会清空整个 Redis 数据库,无法实现按 store 精准清理;正确做法是统一使用单个 Redis store,并借助缓存标签(Cache Tags&a…...

Log-Periodic Modulations in the CMB Low-ℓ Spectrum from Arithmetic Non-Triviality of Elliptic Curves

Log-Periodic Modulations in the CMB Low-ℓ Spectrum from Arithmetic Non-Triviality of Elliptic Curves Author: Jianhua Fang Affiliation: Shihao Jiu Laboratory Abstract The standard ΛCDM model, while remarkably successful, faces persistent anomalies in th…...

想做5v5对战游戏?这套Unity框架直接拿来用

插件简介 Multiplayer Engine – Pro Edition 是一套面向多人游戏开发的完整解决方案,整合了 Unity Gaming Services、Steam 以及 PlayFab 等主流后端服务,支持 P2P(点对点)与 Dedicated Server(专用服务器&#xff09…...

在超大数据集下 DuckDB 与 MySQL 查询速度对比吨

一、什么是urllib3? urllib3 是一个用于处理 HTTP 请求和连接池的强大、用户友好的 Python 库。 它可以帮助你: 发送各种 HTTP 请求(GET, POST, PUT, DELETE等)。 管理连接池,提高网络请求效率。 处理重试和重定向。 支…...

无片外电容LDO电路设计方案:‘完整IP现成电路,含过温过流保护与性能指标流片验证’及学习资源包

无片外电容LDO电路设计 完整IP现成电路,具有过温保护和过流保护,带隙,BUFFER都有 性能指标已流片验证 同时有相关文献、各模块电路功能分析简化计算笔记,适合学习入门不适合纵向可以附赠一些自己学习时觉得比较有帮助的资料。 有好…...

conda简单安装介绍及基础使用(小白版)

目录 一、Conda 基础介绍 1.1 核心定位与两大能力 (1)包管理器(Package Manager) (2)环境管理器(Environment Manager) 1.2 关键特点 1.3 Conda vs Anaconda/Miniconda&#x…...

BilibiliDown终极指南:4步掌握B站视频批量下载与高清画质优化

BilibiliDown终极指南:4步掌握B站视频批量下载与高清画质优化 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mi…...

HTML怎么在GeneratePress中精调图片对齐_GP轻量主题CSS覆盖方法

用CSS覆盖GP默认图片对齐需提高选择器权重(如.site-content img.aligncenter),补display: block配合margin: 0 auto;text-align仅对行内级图片有效;alignnone需加height: auto防溢出;移动端须配media断点。…...

零基础入门:使用CYBER-VISION零号协议学习Python爬虫开发

零基础入门:使用CYBER-VISION零号协议学习Python爬虫开发 你是不是觉得学编程,尤其是像爬虫这种听起来有点“黑客范儿”的东西,门槛特别高?一想到要面对复杂的代码、各种反爬机制,还有那些看不懂的网页结构&#xff0…...

2025届最火的五大降AI率助手推荐榜单

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 使AI率下降的关键之处在于削减机械感以及模式化的表达。其一,要防止运用常见的高…...

被“圈养”的Java开发者:当AI浪潮来袭,你还在用手写HttpClient调大模型吗?

写在前面 2026年,AI早已不是算法工程师的专属领域。每个后端开发者都被卷入了这场浪潮——无论你愿不愿意。 “两年前,大部分Java团队面对大模型浪潮的反应是:‘我们用HTTP调OpenAI的API不就行了?’” 但到了2026年,如…...

2025届学术党必备的六大降重复率工具实测分析

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 伴随人工智能生成内容,就是那个AIGC技术的广泛普及,各个大平台以及学…...

Gemma-3-12b-itGPU算力适配指南:A100/H100/A800多卡并行配置参数详解

Gemma-3-12b-it GPU算力适配指南:A100/H100/A800多卡并行配置参数详解 1. 项目背景与核心价值 Gemma-3-12b-it是基于Google最新大模型架构开发的多模态交互工具,专为需要本地部署大模型的企业和研究机构设计。12B参数规模的模型在图文理解和生成任务上…...

Python+scikit-fuzzy实战:5分钟搞定电机速度模糊控制(附完整代码)

Pythonscikit-fuzzy实战:5分钟搞定电机速度模糊控制(附完整代码) 最近在开发一个智能小车项目时,遇到了电机速度控制的难题。传统PID控制虽然稳定,但面对复杂路况时响应总是不够理想。尝试改用模糊控制后,发…...

C++ P1151 子数整数

文章目录一、题目链接二、参考代码一、题目链接 链接: link 二、参考代码 #include <iostream> #include <string> #include <algorithm> #include <math.h> using namespace std;int main() {int num;cin >> num;int key 0;for (int i 1000…...

STM32G474的COMP比较器,除了保护电路还能这么玩?一个LED灯搞定电压监测

用STM32G474的COMP比较器玩转电压监测&#xff1a;一个LED灯就够了 在嵌入式开发中&#xff0c;我们常常需要监测电压变化&#xff0c;比如电池电量、传感器输出等。传统做法是使用ADC采样&#xff0c;然后通过软件判断阈值。但这种方法需要占用CPU资源&#xff0c;响应速度也受…...

Vue3中keep-alive缓存失效的常见场景与层级关系解析

1. 为什么我的keep-alive不生效&#xff1f; 最近在Vue3项目中遇到一个典型问题&#xff1a;使用keep-alive缓存组件后&#xff0c;发现created和mounted钩子依然会被重复调用。这让我很困惑&#xff0c;明明已经按照文档配置了keep-alive&#xff0c;为什么缓存还是失效了呢&a…...

NativeFB:车规级原生帧缓冲驱动框架设计与实践

1. NativeFB&#xff1a;面向CARIAD车载信息娱乐系统的原生帧缓冲驱动框架1.1 项目定位与工程背景NativeFB 是专为大众集团 CARIAD 车载软件平台设计的轻量级、高确定性帧缓冲&#xff08;Framebuffer&#xff09;驱动框架。其核心目标并非通用 Linux 图形栈的替代品&#xff0…...

蜜罐技术(Honeypot)详解:定义、原理、分类与核心作用

蜜罐技术&#xff08;Honeypot&#xff09;详解&#xff1a;定义、原理、分类与核心作用一、基础定义&#xff1a;什么是蜜罐技术&#xff1f;标题&#xff1a;蜜罐技术&#xff1a;定义与核心思想二、工作原理&#xff1a;蜜罐是如何工作的&#xff1f;标题&#xff1a;蜜罐技…...