嵌入式常用算法:环形缓冲区算法

在嵌入式开发中离不开设备通信,而在通信中稳定性最高的莫过于环形缓冲区算法,当读取速度大于写入速度时,在环形缓冲区的支持下不会丢掉任何一个字节(硬件问题除外)。下面我分享一段由我原创的Ringbuffer代码。

C文件:

[plain]  view plain  copy
  1. /**  
  2.   ******************************************************************************  
  3.   * @file    cx_ringbuff.c  
  4.   * @author  CX  
  5.   * @version V1.0.0.2  
  6.   * @date    2016-07-13  
  7.   * @brief   1.0.0.2 期望帧逻辑优化  
  8.              修改匹配期望帧任务的条件  
  9.              增加匹配期望帧函数  
  10.              1.0.0.1 优化耦合性  
  11.              优化读取逻辑  
  12.              增加多缓冲区支持  
  13.          1.0.0.0 主体架构搭建,完成读写环形结构化  
  14.   ******************************************************************************  
  15.   * @attention  
  16.   *  
  17.   * 项目   :None  
  18.   * 官网   : None  
  19.   * 实验室 :None  
  20.   *  
  21.   ******************************************************************************  
  22.   */  
  23.   
  24. #include "cx_ringbuff.h"  
  25.   
  26.   
  27. /* 除了必须的缓冲区外没有向外部模块公开一个变量,实现高内聚,低耦合 */  
  28. RingBuff_Typedef  RingBuffStruct;  
  29.   
  30.   
  31. /**  
  32. * @brief   缓冲区实例化  
  33. * @param   rb_ptr 缓冲区结构体地址  
  34. * @retval  None  
  35. * @notice  None  
  36. */  
  37. void RingBuff_New(RingBuff_Typedef* rb_ptr)  
  38. {  
  39.     rb_ptr->Readpos = rb_ptr->RxBuff;  
  40.     rb_ptr->Writepos = rb_ptr->RxBuff;  
  41.     rb_ptr->ReadRetStateStruct.Readstate = Fail;  
  42.     rb_ptr->ReadRetStateStruct.ptr = NULL;  
  43.     rb_ptr->RingbufCount = 0;  
  44.     memset(rb_ptr->RxBuff, 0, MaxBuffSize);  
  45. }  
  46.   
  47.   
  48. /**  
  49.   * @brief   定位函数  
  50.   * @param   rb_ptr 缓冲区结构体地址,addr 当前读写地址  
  51.   * @retval  addr+1 or 0   
  52.   * @notice  None  
  53.   */  
  54. unsigned char* NextDataAddrHandle(RingBuff_Typedef* rb_ptr, unsigned char* addr)  
  55. {  
  56.     return (addr + 1) == (rb_ptr->RxBuff + MaxBuffSize) ? rb_ptr->RxBuff : (addr + 1);  
  57. }  
  58.   
  59.   
  60. /**  
  61.   * @brief   读字节函数  
  62.   * @param   rb_ptr 缓冲区结构体地址  
  63.   * @retval  data  
  64.   * @notice  None  
  65.   */  
  66. ReadRetState_Typedef* ReadDataFromRingbuff(RingBuff_Typedef* rb_ptr)  
  67. {  
  68.     if (rb_ptr->RingbufCount > 0)  
  69.     {  
  70.         rb_ptr->ReadRetStateStruct.ptr = rb_ptr->Readpos;  
  71.         rb_ptr->ReadRetStateStruct.Readstate = Success;  
  72.         rb_ptr->Readpos = NextDataAddrHandle(rb_ptr, rb_ptr->Readpos);  
  73.         rb_ptr->RingbufCount--;  
  74.         return &rb_ptr->ReadRetStateStruct;  
  75.     }  
  76.     rb_ptr->ReadRetStateStruct.Readstate = Fail;  
  77.     rb_ptr->ReadRetStateStruct.ptr = NULL;  
  78.     return &rb_ptr->ReadRetStateStruct;  
  79. }  
  80.   
  81.   
  82. /**  
  83.   * @brief   写字节函数  
  84.   * @param   rb_ptr 缓冲区结构体地址,data 写入数据  
  85.   * @retval  None  
  86.   * @notice  None  
  87.   */  
  88. void WriteDataToRingbuff(RingBuff_Typedef* rb_ptr, unsigned char data)  
  89. {  
  90.     *(rb_ptr->Writepos) = data;  
  91.     rb_ptr->Writepos = NextDataAddrHandle(rb_ptr,rb_ptr->Writepos);  
  92.     rb_ptr->RingbufCount++;  
  93. }  
  94.   
  95.   
  96. /**  
  97.   * @brief   读指定包长函数  
  98.   * @param   rb_ptr 缓冲区结构体地址,head 包头,length 包长  
  99.   * @retval  读取状态及数据包地址  
  100.   * @notice  length为整个数据包长即头置尾  
  101. */  
  102. ReadRetState_Typedef* ReadEfectiveFrameFixLength(RingBuff_Typedef* rb_ptr, unsigned char head, unsigned char length)  
  103. {  
  104.     unsigned char count = rb_ptr->RingbufCount;              //标记触发前有效数据大小  
  105.     if (count < length)  
  106.     {  
  107.         rb_ptr->ReadRetStateStruct.Readstate = Fail;  
  108.         rb_ptr->ReadRetStateStruct.ptr = NULL;  
  109.         return &rb_ptr->ReadRetStateStruct;  
  110.     }  
  111.     while (count >= length)  
  112.     {  
  113.         rb_ptr->ReadRetStateStruct = *ReadDataFromRingbuff(rb_ptr);  
  114.         count--;  
  115.         if (rb_ptr->ReadRetStateStruct.Readstate == Success && *rb_ptr->ReadRetStateStruct.ptr == head)  
  116.         {  
  117.             return &rb_ptr->ReadRetStateStruct;  
  118.         }  
  119.     }  
  120.     rb_ptr->ReadRetStateStruct.Readstate = Fail;  
  121.     rb_ptr->ReadRetStateStruct.ptr = NULL;  
  122.     return &rb_ptr->ReadRetStateStruct;  
  123. }  
  124.   
  125.   
  126. /**  
  127.   * @brief   读期望帧  
  128.   * @param   rb_ptr 缓冲区结构体地址,str 期望帧  
  129.   * @retval  读取状态  
  130.   * @notice  None  
  131. */  
  132. ReadRetState_Enum ReadEfectiveFrame(RingBuff_Typedef* rb_ptr, const char* str)  
  133. {  
  134.     unsigned char count = rb_ptr->RingbufCount;                 //标记触发前有效数据大小                  
  135.     unsigned char length = strlen(str);  
  136.     unsigned char i = 0;  
  137.     if (count < length)  
  138.     {  
  139.         return Fail;  
  140.     }  
  141.     while (count >= length)  
  142.     {  
  143.         rb_ptr->ReadRetStateStruct = *ReadDataFromRingbuff(rb_ptr);  
  144.         count--;  
  145.         if (rb_ptr->ReadRetStateStruct.Readstate == Success && *rb_ptr->ReadRetStateStruct.ptr == *(str + i))  
  146.         {  
  147.             count++;  
  148.             i++;  
  149.         }  
  150.         else  
  151.         {  
  152.             i = 0;  
  153.         }  
  154.         if (i == length)  
  155.         {  
  156.             return Success;  
  157.         }  
  158.     }  
  159.     return Fail;  
  160. }  
  161.   
  162.   
  163. /**  
  164.   * @brief   匹配期望帧  
  165.   * @param   rb_ptr 缓冲区结构体地址,str 期望帧所在注册表地址, ExpectFrameCount 期望帧注册表的个数  
  166.   * @retval  读取状态  
  167.   * @notice  None  
  168. */  
  169. ReadRetState_Typedef* MatchExpectFrame(RingBuff_Typedef* rb_ptr, const char** str, unsigned char ExpectFrameCount)  
  170. {  
  171.     unsigned char Retcount = rb_ptr->RingbufCount;                
  172.     unsigned char* RetPos = rb_ptr->Readpos;  
  173.   
  174.     unsigned char i = 0;  
  175.     for (i = 0; i < ExpectFrameCount; i++)  
  176.     {  
  177.         if (ReadEfectiveFrame(rb_ptr, *(str + i)) == Success)  
  178.         {  
  179.             rb_ptr->ReadRetStateStruct.pos = i;  
  180.             rb_ptr->ReadRetStateStruct.Readstate = Success;  
  181.             return &rb_ptr->ReadRetStateStruct;  
  182.         }  
  183.         else  
  184.         {  
  185.             rb_ptr->RingbufCount = Retcount;  
  186.             rb_ptr->Readpos = RetPos;  
  187.         }  
  188.     }  
  189.     rb_ptr->ReadRetStateStruct.Readstate = Fail;  
  190.     return &rb_ptr->ReadRetStateStruct;  
  191. }  
  192.   
  193.   
  194. /******************** (C)COPYRIGHT(2016) YFTC  END OF FILE **********************/  
H文件

[html]  view plain  copy
  1. #ifndef __CX_RINGBUFF_H  
  2. #define __CX_RINGBUFF_H  
  3.   
  4.   
  5. #include "stdlib.h"  
  6. #include "string.h"  
  7.   
  8.   
  9. #define         MaxBuffSize        256        //缓冲区大小可任意设置,但最好为2^X  
  10.   
  11.   
  12. typedef enum  
  13. {  
  14.     Success = 1,  
  15.     Fail = !Success,  
  16. }ReadRetState_Enum;  
  17.   
  18.   
  19. typedef struct  
  20. {  
  21.     ReadRetState_Enum Readstate;                //读状态  
  22.     unsigned char* ptr;                         //读取字节地址  
  23.     unsigned char  pos;                         //期望帧在注册表中位置  
  24. }ReadRetState_Typedef;  
  25.   
  26.   
  27.   
  28. typedef struct  
  29. {  
  30.     unsigned char* Writepos;                    //写入地址  
  31.     unsigned char* Readpos;                     //读取地址  
  32.     unsigned char RingbufCount;                 //有效未读数据大小  
  33.     ReadRetState_Typedef ReadRetStateStruct;    //读缓冲相关  
  34.     unsigned char RxBuff[MaxBuffSize];          //数据缓存区  
  35. }RingBuff_Typedef;  
  36.   
  37.   
  38. void RingBuff_New(RingBuff_Typedef* rb_ptr);  
  39. unsigned char* NextDataAddrHandle(RingBuff_Typedef* rb_ptr,unsigned char* addr);  
  40. ReadRetState_Typedef* ReadDataFromRingbuff(RingBuff_Typedef* rb_ptr);  
  41. void WriteDataToRingbuff(RingBuff_Typedef* rb_ptr,unsigned char data);  
  42. ReadRetState_Typedef* ReadEfectiveFrameFixLength(RingBuff_Typedef* rb_ptr, unsigned char head, unsigned char length);  
  43. ReadRetState_Enum ReadEfectiveFrame(RingBuff_Typedef* rb_ptr, const char* str);  
  44. ReadRetState_Typedef* MatchExpectFrame(RingBuff_Typedef* rb_ptr, const char** str, unsigned char ExpectFrameCount);  
  45.   
  46.   
  47. #endif  

以上就是我所编写的Ringbuffer源码。

从.H文件中可看到Ringbuff的数据结构,当中有读写地址以及有效未读数据大小,以及读状态等。

向外部提供的API接口就是常规的读数据包,读期望帧以及匹配期望帧,整段代码可用于普通的通信数据帧读取,也可以在单片机中用于shell组件的实现。还是希望广大网友能对我的代码进行功能补充,BUG修复等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值