MCU 串口接收环形缓冲区的实现

环形缓冲区

1. 环形缓冲区的特性

1.先进先出

2. 当缓冲区被使用完,且又有新的数据需要存储时,丢掉历史最久的数据,保存最新的数据

现实中的存储介质都是线性的,因此我们需要做一下处理,才能在功能上实现环形缓冲区

算法说明:
1、pHead和pTail分别是连续存储介质的首地址和尾地址
2、pTail - pHead 的值是环形缓冲区的总长度
3、pValid 是使用区域的起始指针,取数据时的起点,当取数据时pValid要发生偏移
4、pValidTail 是使用区域的的结尾指针,存数据时的起点,当存数据时,pValidTail要发生偏移
5、现有长度为addLen字节要存入,当pValidTail + addLen > pTail 时(超出了缓冲区,这时就要绕到开头pHead)
int len1 = pTail - pValidTail;
int len2 = addLen - len1;
pValidTail = pHead + len2;//新的使用区的尾指针
6、判断总长度是否变更,即是否有数据覆盖pValid所指向的区域,如果有,要偏移pValid

2. 算法验证代码

ringBuffer.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "ringBuffer.h"
#define BUFFER_SIZE  16   //缓冲区的长度,可以修改static u32 validLen;//已使用的数据长度
static u8* pHead = NULL;//环形存储区的首地址
static u8* pTail = NULL;//环形存储区的结尾地址
static u8* pValid = NULL;//已使用的缓冲区的首地址
static u8* pValidTail = NULL;//已使用的缓冲区的尾地址/** 初始化环形缓冲区* 环形缓冲区这里可以是malloc申请的内存,也可以是Flash存储介质* */
void initRingbuffer(void)
{if(pHead == NULL){pHead = (u8*) malloc(BUFFER_SIZE);}pValid = pValidTail = pHead;pTail = pHead + BUFFER_SIZE;validLen = 0;
}/** function:向缓冲区中写入数据* param:@buffer 写入的数据指针* 		 @addLen 写入的数据长度* return:-1:写入长度过大* 		  -2:缓冲区没有初始化* */
int wirteRingbuffer(u8* buffer,u32 addLen)
{if(addLen > BUFFER_SIZE) return -2;if(pHead==NULL) return -1;assert(buffer);//将要存入的数据copy到pValidTail处if(pValidTail + addLen > pTail)//需要分成两段copy{int len1 = pTail - pValidTail;int len2 = addLen - len1;memcpy( pValidTail, buffer, len1);memcpy( pHead, buffer + len1, len2);pValidTail = pHead + len2;//新的有效数据区结尾指针}else{memcpy( pValidTail, buffer, addLen);pValidTail += addLen;//新的有效数据区结尾指针}//需重新计算已使用区的起始位置if(validLen + addLen > BUFFER_SIZE){int moveLen = validLen + addLen - BUFFER_SIZE;//有效指针将要移动的长度if(pValid + moveLen > pTail)//需要分成两段计算{int len1 = pTail - pValid;int len2 = moveLen - len1;pValid = pHead + len2;}else{pValid = pValid + moveLen;}validLen = BUFFER_SIZE;}else{validLen += addLen;}return 0;
}/** function:从缓冲区内取出数据* param   :@buffer:接受读取数据的buffer*		    @len:将要读取的数据的长度* return  :-1:没有初始化*	 	    >0:实际读取的长度* */
int readRingbuffer(u8* buffer,u32 len)
{if(pHead==NULL) return -1;assert(buffer);if(validLen ==0) return 0;if( len > validLen) len = validLen;if(pValid + len > pTail)//需要分成两段copy{int len1 = pTail - pValid;int len2 = len - len1;memcpy( buffer, pValid, len1);//第一段memcpy( buffer+len1, pHead, len2);//第二段,绕到整个存储区的开头pValid = pHead + len2;//更新已使用缓冲区的起始}else{memcpy( buffer, pValid, len);pValid = pValid +len;//更新已使用缓冲区的起始}validLen -= len;//更新已使用缓冲区的长度return len;
}/** function:获取已使用缓冲区的长度* return  :已使用的buffer长度* */
u32 getRingbufferValidLen(void)
{return validLen;
}/** function:释放环形缓冲区* */
void releaseRingbuffer(void)
{if(pHead!=NULL) free(pHead);pHead = NULL;
}

ringBuffer.h

#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
typedef unsigned char u8;
typedef unsigned int u32;void initRingbuffer(void);
int wirteRingbuffer(u8* buffer,u32 len);
int readRingbuffer(u8* buffer,u32 len);
u32 getRingbufferValidLen(void);
void releaseRingbuffer(void);#endif /* RINGBUFFER_H_ */

 测试 main 函数

#include <stdio.h>
#include <stdlib.h>
#include "ringBuffer.h"
// 主函数
int main()
{char c;int readLen;u8 readBuffer[10];//setvbuf(stdout,NULL,_IONBF,0); //pinrtf、putchar不能立马输出,打开此注释initRingbuffer();printf("Please enter a line [blank line to terminate]> ");do{c=getchar();putchar(c);switch(c){case 'Q':goto exit;break;case 'R':readLen = readRingbuffer(readBuffer,10);printf("readRingbuffer len:%d\n",readLen);if(readLen > 0){printf("readRingbuffer:");for(int i=0;i<readLen;i++){printf("%c ",(char)readBuffer[i]);}printf("\n");}break;default :if(c!='\n') wirteRingbuffer((u8*)&c,1);break;}}while (1);exit:releaseRingbuffer();printf("exit.\n");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/716905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[计算机网络]--I/O多路转接之poll和epoll

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、poll函…

web漏洞与规避

文章目录 一、XSS 跨站脚本攻击1.1 XSS攻击的主要类型反射型XSS存储型XSSDOM型XSS 1.2 前端开发如何应对XSS 二、CSRF 跨站请求伪造2.1 CSRF例子2.2 前端开发如何应对CSRF 三、SQL 注入3.1 前端如何防御SQL注入 四、前端如何使用CSP 一、XSS 跨站脚本攻击 攻击者通过在受害者的…

stm32学习笔记:IIC通信(未完)

概述 第一块&#xff1a;介绍协议规则&#xff0c;然后用软件模拟的形式来实现协议。 第二块&#xff1a;介绍STM32的iic外设&#xff0c;然后用硬件来实现协议。 程序一现象&#xff1a;通过软件I2C通信&#xff0c;对MPU6050芯片内部的寄存器进行读写&#xff0c;写入到配…

【Synchronized同步原理】

Synchronized同步原理 1. synchronized的使用&#xff1f;2. 如何保证线程安全的&#xff1f;3.可重入原理&#xff08;加锁次数计数器&#xff09;4. 原子性和可见性(顺序性) 1. synchronized的使用&#xff1f; 对象锁方法锁类锁 2. 如何保证线程安全的&#xff1f; publi…

关于数据提交上传服务端的数据类型以及项目打包上线的流程

1 请求头的类型&#xff1a; content-type&#xff1b; 01: application/json 数据以json格式请求&#xff1a;{"key":"value"} 02: application/x-www.form-urlencoded from表单的数据格式 name"zs"&age12 03 mutipart/form-data…

重学SpringBoot3-自动配置机制

重学SpringBoot3-自动配置机制 引言Spring Boot 自动配置原理示例&#xff1a;Spring Boot Web 自动配置深入理解总结相关阅读 引言 Spring Boot 的自动配置是其最强大的特性之一&#xff0c;它允许开发者通过最少的配置实现应用程序的快速开发和部署。这一切都得益于 Spring …

OmniPlan Pro mac版:简单、智能,项目管理新选择!

OmniPlan Pro是一款功能强大的项目管理软件&#xff0c;它以其直观的用户界面和丰富的功能&#xff0c;帮助用户轻松管理各种复杂的项目。无论是个人任务还是团队协作&#xff0c;OmniPlan Pro都能提供全面的解决方案&#xff0c;让项目管理变得更加简单高效。 OmniPlan Pro软…

从0开始回顾Mysql --- MySQL初体验

大白话从0开始回顾MySQL&#xff0c;去除了一些繁琐的操作的演示以及内容&#xff0c;如MySQL安装等&#xff0c;本篇文章适合复习MySQL语法&#xff0c;学习MySQL语句&#xff0c;对MySQL不太熟练的同学&#xff0c;希望对大家有一些帮助。 MySQL初体验 首先&#xff0c;我将…

如何在Window系统部署VisualSVN服务并结合cpolar实现无公网ip远程访问

文章目录 前言1. VisualSVN安装与配置2. VisualSVN Server管理界面配置3. 安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4. 固定公网地址访问 前言 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统…

数字孪生与智慧交通的融合发展:推动交通行业数字化转型,构建智慧城市新生态

随着信息技术的快速发展和城市化进程的深入推进&#xff0c;交通行业正面临着前所未有的机遇与挑战。传统的交通管理模式已难以满足日益增长的交通需求&#xff0c;而数字化转型则成为了推动交通行业创新发展的必由之路。数字孪生技术作为一种前沿的信息技术手段&#xff0c;为…

基于springboot+vue的公寓报修管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

每天的三哥牌小鸡腿没了

查看印度基金(164824)公告&#xff0c;从2024年2月28日起&#xff0c;暂停印度基金的申购&#xff0c;限额100块的一拖七套利告一段落。这意味着看好印度股市的国内投资者&#xff0c;以后只能通过在场内买入获得份额。 关于暂停申购的原因&#xff0c;官方说是为保护基金持有…

重磅!交通领域顶级会议TRB会议将进行重大改革

美国交通研究委员会年会&#xff08;Transportation Research Board annual meeting,以下简称TRB会议&#xff09;是由美国交通研究委员会举办的交通领域的国际顶级会议。该会议每年举办一次&#xff0c;在华盛顿特区召开。TRB会议是交通研究领域知名度最高的学术会议之一&…

安装 node 错误的配置环境变量之后使用 npm 报错

安装 node 错误的配置环境变量之后使用 npm 报错 node:internal/modules/cjs/loader:1147 throw err; ^ Error: Cannot find module ‘F:\ACodeTools\Node\node_modules\npm\bin\node_modules\npm\bin\npm-cli.js’ at Module._resolveFilename (node:internal/modules/cjs/loa…

基于springboot实现企业员工绩效考评系统项目【项目源码+论文说明】

基于springboot实现企业员工绩效考评系统演示 摘要 时代的变化速度实在超出人类的所料&#xff0c;21世纪&#xff0c;计算机已经发展到各行各业&#xff0c;各个地区&#xff0c;它的载体媒介-计算机&#xff0c;大众称之为的电脑&#xff0c;是一种特高速的科学仪器&#xf…

AI-数学-高中-32-统计-样本空间与随机事件

原作者视频&#xff1a;【概率】【一数辞典】1样本空间与随机事件_哔哩哔哩_bilibili 1.随机试验&#xff1a; 2.样本点、样本空间、有限样本空间&#xff1a; 示例1 示例2 3.事件&#xff1a; 示例&#xff1a;

[DEBUG] spring boot-如何处理链接中的空格等特殊字符

问题&#xff1a; get或者post中提交的内容可能有空格、#等特殊字符&#xff0c;不做处理的话可能解析错误。 解决&#xff1a; html中&#xff1a; <a th:href"{/listSgrna(id${item.getGeneId()},geneName${item.getGeneName()},genome${genome},sgrnaNum${sgrnaN…

Qt CMake 国际化相关配置

文章目录 更新ts文件发布ts文件 本来用qmake使用pro文件很简单的一件事&#xff0c;结果用cmake折腾了半天。 何必呢~ 参考&#xff1a;QT6.3 CMake 多语言切换 这是我的 cmake_minimum_required(VERSION 3.16)project(testQml3_6 VERSION 0.1 LANGUAGES CXX)set(CMAKE_AUTO…

06.QT信号和槽-1

一、信号和槽概述 在Qt中&#xff0c;用户和控件的每次交互过程称为一个事件。比如"用户点击按钮"是一个事件&#xff0c;"用户关闭窗口"也是一个事件。每个事件都会发出一个信号&#xff0c;例如用户点击按钮会发出"按钮被点击"的信号&#xff…

Java练习(第5天)【总结】在字符串中寻找特定的字符(5种方法)

问题描述&#xff1a;在字符串中寻找特定字符 1、第1次出现位置 实现函数原型&#xff1a; int indexOf(char c) Java代码&#xff1a; import java.io.*; public class Way_1 {public static void main(String args[]){String str "Geeks for Geeks is a computer s…