嵌入式硬件通信接口-使用RingBuffer处理数据(二)

2023-10-27

文章首发于同名微信公众号:DigCore

欢迎关注同名微信公众号:DigCore,及时获取最新技术博文。

 

经过上一篇《嵌入式硬件通信接口-使用RingBuffer处理数据(一)》简单了解循环缓冲区,读代码后,接着开始设计自己的循环缓冲区功能模块。

设计思路

这里设计的难点在于,如何把控tail这个写地址,每增加一个数据时tail自增,在写的过程中,如果使用缓冲区的所有空间,那么head等于tail的时候,这个情况可能是空或者满,需要在程序设计时候,多加留意。

在实际项目使用中,仍需要考虑的两个问题:

  1. 读多个字节时,缓冲区内可读数量比用户想读的个数少,这时候是逐字节把可读的都读出来,还是直接报错?

  2. 写多个字节时,缓冲区内可写数量比用户想写的个数少,这时候是逐字节把可写的都写满,还是直接报错?

鉴于这样的问题,在读多字节和写多字节这两个接口上增加一个变量mode,用于设定接口在读写多字节时遇到长度超出范围,是逐字节继续处理还是直接报错。

还有,相比于上一篇文章中参考的源码,这里的设计思路采用的是地址指针的方式,而不是偏移量

并且为了区别于缓冲区空或者满,将牺牲掉一个字节的空间:当缓冲区空的时候head等于tail,当缓冲区满的时候head在tail相邻的后一个位置。

本次的设计,使用head指向缓冲区中可读数据的首地址,使用tail指向缓冲区中可读数据的末地址(同时这也是可写数据的首地址):

数据流是55 04 18 02 07
B7这样的一连串16进制数,接收端先收到的是0x55,后收到的是0x04,以这样的顺序逐字节通过物理层接口接收。这也是一个数据包的常规帧结构,也符合人从左到右的阅读顺序。

所以在这里以head指向的是数据包的头,tail指向数据包的尾,head到tail之间就是一个可读数据的范围,同时,tail指向的是可写区域的首地址,当有新的数据进来时,新的数据会被从tail地址继续写到内存,而后tail在环内递增。

知道了循环缓冲区的这几个属性:缓冲区大小、缓冲区在内存中的地址范围、存取数据时的读写地址。可根据这些属性,构造一个循环缓冲区的结构体:

typedef struct{

uint32_t size;

uint8_t *head;

uint8_t *tail;

uint8_t *buff;

}rb_t;

ringbuffer简写rb,其中

size表示用户申请成功的或定义的buffer空间大小;

head是一个地址指针,指向缓冲区读的首地址;

tail也是个地址指针,指向缓冲区读的末地址(也就是写的首地址);

buff还是一个指针,一直指向用户定义或者程序动态申请的内存buffer首地址。

当我们需要使用环形缓冲区前,需要定义数组变量或者申请内存,作为数据实际存储的地方,同时定义一个rb_t的结构体,用于关联数组变量或者内存空间。

功能模块将完成以下接口:

  1. 初始化

  2. 可读数量

  3. 可写数量

  4. 读一个字节

  5. 读多个字节

  6. 写一个字节

  7. 写多个字节

  8. 查看指定偏移的数据

  9. 查看指定数据是否在缓冲区并取其在内存的地址

  10. 复位清空

关于命名,暂且做个说明:dcclib是DigCore_Library的简写,这是功能模块库层的代码;rb是ringbuffer模块简写。

初始化

初始化的目的是把用户定义的将要使用的数组,与结构体变量关联起来,后续的操作脱离数组,直接操作结构体变量,正如此,结构体变量的初始化后,将对size、head、tail、buff各个成员赋值。

(截图略.)

可读数量

head指向的是可读数据的首地址,该地址内是有数据可以读的;

hail指向的是可读数据的末地址,该地址内没有数据可读,同时tail指向的是一个空的字节,作为写的首地址。

可写数量

这个需要留意的是总有一个字节空间不可写,因此size大小的空间内,除了可读,剩下就是一个空字节和可写数量

读一个字节

读一个字节时,基于指针地址的操作模式,需要留意的是读指针自增后超过缓冲区的范围时,将读指针折返回到缓冲区的起始位置。

读多个字节

读多个字节,必然是基于读一个字节的基础上实现的。这里相比于前一篇文章提到的参考项目源码,不同的是增加了读模式的选择,当要读的数据个数大于可读数量时,可以利用mode来选择是否仍然逐字节地把能读的都读出来。

如果在调用接口时mode设为FORCE的强制读取,要读的数据个数大于可读数量时,将以RET_RB_RDWRN的错误返回码,旨在说明读取的数据不足,但是也已经把可读的都读出了

写一个字节

写一个字节时,基于指针地址的操作模式,需要留意的是写指针自增后超过缓冲区的范围时,将写指针折返回到缓冲区的起始位置。

写多个字节

写多个字节,必然是基于写一个字节的基础上实现的。这里相比于前一篇文章提到的参考项目源码,不同的是增加了写模式的选择,当要写的数据个数大于可写数量时,可以利用mode来选择是否仍然逐字节地把能写的都写进去。

如果在调用接口时mode设为FORCE的强制读写入,要写的数据个数大于可写数量时,将以RET_RB_WRWRN的错误返回码,旨在说明可写的空间不足,但是也已经把剩余空间的都写满了

查看指定偏移的数据

查看指定数据在缓冲区内存的位置

为了在按地址寻数据时不越界超出Buffer范围,这里分情况处理,分别head在tail之前或之后的两种情况处理。

复位清空

其实复位情况,也只是对读写指针操作,当读写指针在同一个位置时,就表示空。实现办法可以是将head赋值给tail,或者将缓冲区的起始地址都重新赋值给head和tail。

其实这两种办法都可以,因为对于环形缓冲区而言,它只关心head和tail的指针地址,而不关心对应内存块的首末

同样复位的时候也可以将内存中的数据清零,memset函数实现。

到此,环形缓冲区模块的代码基本搞定了。

还需要执行调试验证,为了验证各个接口的执行效果,编写了测试代码,并且将Debug结果打印输出,有条件可以在线仿真,并且可以具体查看内存中的真实数据!

附上Debug过程中对变量的观察的截图:

同样附上Debug过程中对Buffer在内存中呈现的截图:

参考资料:

《Circular_buffer》@维基百科

https://en.wikipedia.org/wiki/Circular_buffer

《环形缓冲器》@百度百科

https://baike.baidu.com/item/%E7%8E%AF%E5%BD%A2%E7%BC%93%E5%86%B2%E5%99%A8

《Ring-Buffer》@Github

https://github.com/AndersKaloer/Ring-Buffer

E:\\Software\\WebSite\\gitee\\digcore\\site_img\\DigCore_Blog_Follow.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式硬件通信接口-使用RingBuffer处理数据(二) 的相关文章

  • 超市运营情况分析

    超市运营情况分析 本文选取的数据源涵盖了2017年至今的客户 订单 地点和产品数据 本文主要聚焦出现负利润的省 自治区的运营情况 对其出现负利润的原因加以探讨 并分析预测这些省 自治区未来的利润情况 对超市的运营管理决策提供有效的数据支持
  • Shell数组:shell数组的定义、数组长度

    Shell在编程方面比Windows批处理强大很多 无论是在循环 运算 bash支持一维数组 不支持多维数组 并且没有限定数组的大小 类似与C语言 数组元素的下标由0开始编号 获取数组中的元素要利用下标 下标可以是整数或算术表达式 其值应大
  • qt超易实现录屏程序的方法

    QT录屏程序的实现 1 获取桌面的图像 The QApplication desktop function is used to get an instance of QDesktopWidget QApplication desktop
  • Git删除本地在远端已经删除的分支

    git remote prune origin
  • python gzipped source tarball,下载及安装Python详细步骤

    安装python分三个步骤 下载python 安装python 检查是否安装成功 1 下载Python 2 选择下载的版本 3 点开Download后 找到下载文件 Gzipped source tarball 是Linux系统下载的版本
  • python3.7成功换虚拟环境python3.6

    目录 1 打开CMD 查看自己有多少虚拟环境 2 打开anaconda prompt 终端 创建 3 6环境 3 在pycharm中从3 7正确换配置为3 6环境 1 打开CMD 查看自己有多少虚拟环境 C Users Administra
  • shell 中的单行注释和多行注释

    今天在学习shell编程的时候 当自己想对多行进行注释时 发现自己不会 所以在网上去查询下 参考 作者 lansesl2008 地址 http blog csdn net lansesl2008 article details 205583
  • 疯传全网网络10个运维巡检脚本以及使用小技巧

    哈喽大家好 欢迎来到虚拟化时代君 XNHCYL 大家好 我是虚拟化时代君 一位潜心于互联网的技术宅男 这里每天为你分享各种你感兴趣的技术 教程 软件 资源 福利 每天更新不间断 福利不见不散 第1章 前言 巡检脚本在网络运维中非常重要 近期
  • Jenkins远程命令执行漏洞(CVE-2018-1000861)

    声明 好好学习 天天向上 漏洞描述 Jenkins使用Stapler框架开发 其允许用户通过URL PATH来调用一次public方法 由于这个过程没有做限制 攻击者可以构造一些特殊的PATH来执行一些敏感的Java方法 通过这个漏洞 我们
  • C单元测试框架——CMockery (1) 简介

    cmockery 是google发布的用于C单元测试的一个轻量级的框架 主要特点 免费且开源 google提供技术支持 轻量级的框架 使测试更加快速简单 避免使用复杂的编译器特性 对老版本的编译器来讲 兼容性好 并不强制要求待测代码必须依赖
  • 【设计模式】-设计模式总目录

    设计模式 重要性不多说了 之前在简书上简单总结过 这次再来总结一次 更详细版 以此加深印象和帮助理解 01 单例模式 https blog csdn net lovexiaotaozi article details 83896573 02
  • Java并发编程——ReentrantLock重入锁解析

    重入锁 所谓重入锁 即支持重入性 表示能够对共享资源重复加锁 即当前线程获取该锁再次获取不会被阻塞 重入性 在线程获取锁的时候 如果已经获取锁的线程是当前线程的话则直接再次获取成功 由于锁会被获取n次 那么只有锁在被释放同样的n次之后 该锁
  • 二叉树的层序遍历,以及求层数

    二叉树的中序遍历 最主要的一种方法是用队列 Queue 来实现 下面贴出一份实现代码 class Tree int data Tree lchild 左孩子 Tree rchild 右孩子 以下是主要方法 public static voi
  • 自己实现telnet程序

    转自 http blog csdn net gujintong1110 article details 44278535 include
  • Metasploitable渗透测试实战:ms17-010

    漏洞简介 永恒之蓝 即ms17 010 是指2017年4月14日晚 黑客团体Shadow Brokers 影子经纪人 公布一大批网络攻击工具 其中包含 永恒之蓝 工具 永恒之蓝 利用Windows系统的SMB漏洞可以获取系统最高权限 5月1
  • 论文解读:Improving Nighttime Driving-Scene Segmentation via Dual Image-adaptive Learnable Filters

    论文地址 https arxiv org abs 2207 01331 发表时间 Submitted on 4 Jul 2022 v1 last revised 20 Mar 2023 this version v2 项目地址 https
  • C语言穷举解决最大子序列含测试

    题目再现 设给定一个整数序列 a 1 a 2
  • Python语言:列表初体验

    列表是Python中的一个对象 他类似于C语言中的数组 可以存储许多数据 也可以称之为数据集合 他原则是可以存储不同类型的数据 一般不建议这样使用 有点奇怪 一般情况下一个列表中保存的都是同一种类型的数据 列表的创建 列表 list 是把数

随机推荐

  • qml界面参数传递、返回

    背景 设计设置界面时需要在键盘上设置数值 设定完返回时需要知道返回值是什么 如果用上下级关系实现可能很方便 但是会重复加载按键模块 觉得这样不好 想用stackView push url 初始值 设定后的值 这样的方式 1 想过用带参数信号
  • Java事件机制简介 内含面试题

    面试题分享 云数据解决事务回滚问题 点我直达 2023最新面试合集链接 2023大厂面试题PDF 面试题PDF版本 java python面试题 项目实战 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转clo
  • 编程是一门技术,更加是一门艺术

    最近一段时间在学习 大话设计模式 书籍开篇就提到 编程是一门技术 更加是一门艺术 这句经典 读罢 我不得不被作者程序设计模式这种与众不同的思维所折服 其实软件编程真的是一门了不起的艺术 谈及 艺术 人们自然会联想到 美 技艺 灵感 等词 但
  • 开关电源输出纹波主要来源五个方面?示波器测纹波方法?

    一 开关电源纹波来源 以20M示波器带宽为限制标准 电压设为PK PK 也有测有效值的 去除示波器控头上的夹子与地线 因为这个本身的夹子与地线会形成环路 像一个天线接收杂讯 引入一些不必要的杂讯 使用接地环 不使用接地环也可以 不过要考虑其
  • armeabi和armeabi-v7a

    在我们android APK的根目录有一个 libs文件夹 此文件夹下包含了armeabi 和armeabi v7a两个文件夹 我们的c代码编译成的本地库 各种 so 就会放在这两个文件夹其中的一个 那armeabi v7a 与 armea
  • 《机器学习》(西瓜书)第六章

    6 1 间隔与支持向量 对于两类训练样本分开的超平面很多 我们需要找到对训练样本局部扰动的 容忍 性最好的那一个 对未见示例的泛化能力最强 鲁棒性 一个系统或组织抵御或克服不利条件的能力 距离超平面最近的几个训练样本能够正确分类 他们被称为
  • jdk1.8新特性之Lambda表达式

    目录 一 为什么使用lambda表达式 二 lambda 表达式语法 一 为什么使用lambda表达式 1 lambda是一个匿名函数 我们可以把lambda表达式理解为是一段可以传递的代码 将代码像数据一样进行传递 二 lambda 表达
  • 性能测试基础知识(一)性能测试策略

    性能测试策略 一 什么是性能测试 二 性能测试的目的 三 性能测试策略 1 基准测试 2 并发测试 3 负载测试 4 压力测试 5 其他测试 一 什么是性能测试 性能测试是在一定的负载1条件下 系统的响应时间等特性是否满足特定的性能需求 需
  • 毕业设计 单片机stm32智能大棚监控护理系统 - lora 远程通信

    文章目录 0 前言 1 简介 2 主要器件 3 实现效果 4 设计原理 4 1 lora无线通信 4 2 MG812二氧化碳监测模块 4 3 MQ 2烟雾传感器 5 部分核心代码 6 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度
  • 如何用DockArray的子索引实现嵌套数据的搜索

    注 本篇文章推荐以 Colab NoteBook 的形式查看 并在浏览器中直接运行代码 链接 https colab research google com github jina ai workshops blob main notebo
  • 在Linux下g++、make、cmake的区别以及优劣

    在Linux下g make cmake的区别以及优劣 1 引言 在Linux环境下进行C 编程时 我们通常需要使用编译器和构建工具来完成编译 构建和管理工作 其中 g make和cmake都是常用的工具 本文将分析它们之间的区别以及优劣 2
  • java+MySQL 基于ssm的网上书店图书商城

    随着现代图书商城的快速发展 可以说图书商城已经逐渐成为现代图书商城过程中最为重要的部分之一 但是一直以来我国传统的图书商城并没有建立一套完善的行之有效的图书商城系统 传统的图书商城已经无法适应高速发展 无论是从效率还是从效果来看都远远的和预
  • 安徽大学计算机考研经验贴

    现在是2021年4月6日 距离接受拟录取过去已经整整一周了 之前一直想写点什么 一方面算是对备考这一年的一个总结 另一方面也可以给学弟学妹们留下一点 经验 先说明下我的情况 初试70左右 复试20名左右 总排名50上下 专业课排名20名以内
  • 华为OD机试真题 (python)之最小循环子数组

    题目描述 最小循环子数组 给定一个由若干整数组成的数组nums 请检查数组是否是由某个子数组重复循环拼接而成 请输出这个最小的子数组 输入描述 第一行 输入数组只中元素个数n 1 sn s 100000第二行输入数组的数字序列nums 以空
  • vertical-align详细介绍

    1 定义 vertical align是一个CSS属性 用于指定行内元素或表格单元格中内容的垂直对齐方式 它可以应用于行内元素 表格单元格或表格单元格中的内容 该属性可以接受多个值 包括关键字 如top middle bottom 长度单位
  • 毕业设计c语言课程设计,毕业设计_c语言_课程设计.doc

    毕业设计 c语言 课程设计 课 程 设 计 报 告 课程名称 C语言程序设计 课题名称 通讯录管理系统 专 业 汽车服务 班 级 0901班 学 号 座机电话号码0114 姓 名 伏铄臻 指导教师 王宁 陈多 2010年9月12日 湖南工程
  • Svnsync:Subversion备份版本库的好工具

    Svnsync Subversion备份版本库的好工具 From SVN知识库 Revision as of 22 35 2008年2月19日 view current revision Older revision Newer revis
  • 两种高性能I/O设计模式(Reactor/Proactor)的比较

    两种高性能I O设计模式 Reactor Proactor 的比较 综述 这篇文章探讨并比较两种用于TCP服务器的高性能设计模式 除了介绍现有的解决方案 还提出了一种更具伸缩性 只需要维护一份代码并且跨平台的解决方案 含代码示例 以及其在不
  • STM32自带温度传感器

    上面是我的微信和QQ群 欢迎新朋友的加入 F4的芯片有自带的温度传感器 测量范围是 40到125摄氏度 误差1 5 数据手册上的说法 温度的测量是通过ADC端口进行的 配置外部时钟 时钟树我配置主频为168M 生成工程 在主函数加上几句话
  • 嵌入式硬件通信接口-使用RingBuffer处理数据(二)

    文章首发于同名微信公众号 DigCore 欢迎关注同名微信公众号 DigCore 及时获取最新技术博文 经过上一篇 嵌入式硬件通信接口 使用RingBuffer处理数据 一 简单了解循环缓冲区 读代码后 接着开始设计自己的循环缓冲区功能模块