找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6020|回复: 3
打印 上一主题 下一主题
收起左侧

[开源]轻量级环形缓冲区Ring Buffer,非常适合用于MCU嵌入式平台的串口收发

  [复制链接]
跳转到指定楼层
楼主
Ring Buffer是一个基于C语言开发的轻量级环形缓冲区,适用于各嵌入式平台的串口收发等应用场景;

相较于普通的收发缓冲数组,环形缓冲区的操作更加简单,性能更加强大;
使用Ring Buffer提供的函数,可以轻松实现数据的读写、查询、删除等操作,不需要编写复杂的地址记录、读写计数等代码,减少了数据指针溢出、数据被覆盖的风险;
同时Ring Buffer还提供了可自定义分隔关键字的插入、查找等功能,运用在嵌入式的串口收发中可以实现多段数据的储存,段落之间分隔独立,读写缓冲区不再受到硬件时序的阻塞,降低串口对芯片实时响应的要求并提升了数据传输的可靠性;

代码已在GD32F130C8T6 MCU平台上通过编译,已进行过大量数据的串口收发压力测试,暂未发现显性BUG;
项目开源地址:Github



2021.01.19 v1.0.0 发布第一版本
2021.01.24 v1.1.0 增加匹配字符查找函数
2021.01.27 v1.2.0 重制匹配字符查找函数,现已支持8位到32位关键词查询
2021.01.28 v1.3.0 复位函数修改为删除函数、增加关键词插入函数(自适应大小端)
2021.01.30 v1.3.1 修复String读写函数的小概率指针溢出错误
持续更新中,欢迎大家使用,如果有BUG请到Github上及时向我反馈,谢谢

同时我在GD32F130平台上基于Ring Buffer库开发了一款单片机串口收发框架UIO,开发UIO的目的也是为了更好的利用Ring Buffer的特点,在实际使用环形缓冲的过程中不断的优化与改进;
使用UIO后,你可以在单片机中同时缓存好几条串口指令却不需要实时处理,等到单片机忙完其他阻塞任务后再将接收缓存的串口数据逐条读出并逐条处理,从容不迫;
UIO的大部分代码与平台分离,移植简单,同时对硬件串口外设进行封装,在应用层开发的时候非常方便,UIO仍在加紧时间开发并测试,届时将会第一时间开源分享给大家吐槽,敬请期待吧!

欢迎关注我的b站视频账号:bilibili

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:826745 发表于 2021-1-30 12:12 | 只看该作者
复制库文件至工程中,在源代码中引用 Ring Buffer 头文件;
新建一个 uint8_t 数组,数组的大小即是环形缓冲区的大小;
新建 Ring Buffer 操作句柄;
初始化 Ring Buffer 操作句柄,将其与刚才新建的数组绑定,转换成环形缓冲区;
这时候我们就可以使用库提供的各种函数对新建的缓冲区进行读写等操作;
函数详细内容请在编程的过程中参考ring_buffer.c内的注释;
回复

使用道具 举报

板凳
ID:826745 发表于 2021-1-30 12:13 | 只看该作者
在这里我展示了如何新建并初始化Ring Buffer、读写环形缓冲、查询数据长度等基础操作
您可以了解到Ring Buffer的函数命名与参数的风格和基本的使用方法
  1. #include <stdio.h>
  2. #include <ring_buffer.h>

  3. #define Read_BUFFER_SIZE        256

  4. int main()
  5. {
  6.     //新建缓冲区数组与Ring Buff操作句柄
  7.     uint8_t buffer[Read_BUFFER_SIZE] ;
  8.     ring_buffer RB ;

  9.     //初始化Ring Buff操作句柄,绑定缓冲区数组;
  10.     Ring_Buffer_Init(&RB, buffer, Read_BUFFER_SIZE);

  11.     //向环形缓冲区写入一段字节和一个字节
  12.     Ring_Buffer_Write_String(&RB, "hello world", 11);
  13.     Ring_Buffer_Write_Byte(&RB, '!');

  14.     //获取已储存的数据长度,读出环形缓冲区中的数据并打印
  15.     uint32_t num = Ring_Buffer_Get_Lenght(&RB);
  16.     uint8_t get[16] ;
  17.     Ring_Buffer_Read_String(&RB, get, num);
  18.     printf("%s", get);
  19.    
  20.     return 0 ;
  21. }
复制代码
回复

使用道具 举报

地板
ID:826745 发表于 2021-1-30 12:13 | 只看该作者
除了基本的读写操作之外,为了更好的利用环形这一特点,我加入了分隔关键词、查询关键词、删除数据等功能
基于这些功能您可以在串口收发中实现多段数据的缓存与准确读取;降低了实时性响应的要求、提升了串口收发的性能
  1. #include <stdio.h>
  2. #include <ring_buffer.h>

  3. #define Read_BUFFER_SIZE        256

  4. //设定一个分隔关键词和关键词的长度(字节)
  5. #define SEPARATE_SIGN       0xCCFB22AA
  6. #define SEPARATE_SIGN_SIZE  4

  7. int main()
  8. {
  9.     //新建缓冲区数组与Ring Buff操作句柄
  10.     uint8_t buffer[Read_BUFFER_SIZE] ;
  11.     ring_buffer RB ;

  12.     //初始化Ring Buff操作句柄,绑定缓冲区数组;
  13.     Ring_Buffer_Init(&RB, buffer, Read_BUFFER_SIZE);

  14.     //记录段落数量
  15.     uint8_t String_Count = 0 ;

  16.     //向环形缓冲区写入三段数据,每段之间插入一个分隔关键词
  17.     Ring_Buffer_Write_String(&RB, "ABCDEFGHIJK\r\n", 13);//写入一段数据
  18.     Ring_Buffer_Insert_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE);//插入一个分隔关键词
  19.     String_Count ++ ;//记录段落数量 +1

  20.     Ring_Buffer_Write_String(&RB, "abcdefg\r\n", 9);
  21.     Ring_Buffer_Insert_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE);
  22.     String_Count ++ ;

  23.     Ring_Buffer_Write_String(&RB, "1234\r\n", 6);
  24.     Ring_Buffer_Insert_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE);
  25.     String_Count ++ ;

  26.     while(String_Count != 0)
  27.     {
  28.         uint8_t get[16] ;
  29.         //获得头指针到关键词高位的距离,距离-1得到第一段数据的长度
  30.         uint8_t lenght = Ring_Buffer_Find_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE) - 1 ;
  31.         Ring_Buffer_Read_String(&RB, get, lenght);//读取一段数据,保存到get数组
  32.         printf("%s", get);//打印数据
  33.         Ring_Buffer_Delete(&RB, SEPARATE_SIGN_SIZE);//删除分隔关键词的长度的数据,即删除关键词
  34.         String_Count -- ;//记录段落数量 -1
  35.     }

  36.     return 0 ;
  37. }
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表