循环buffer的实现

1.循环buffer的特点

1、先进先出
2、当空闲缓冲区用完,且又有新的数据需要存储时,覆盖历史数据,保存新的数据

3、环形缓冲区在实现时采用的是线型的存储结构

4、线型存储中需要四个指针,分别为缓冲区首地址指针(pHead)、尾地址指针(pTail)、有效数据起始指针(pValid)、有效数据尾指针(pValidTail)。其中pValid<pValidTail或者pValid>=pValidTtail,如下图所示:

2.循环buffer的实现

#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;
}

 

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
串口循环buffer是一种用于缓存数据的机制,常用于串口通信中。它通过循环队列的方式,将接收到的数据流先缓存到循环buffer中,然后再从循环buffer中取出数据进行后续处理。这种机制可以有效地避免解析数据帧时繁琐的拼接处理。在WINCE开发中,循环buffer常被用于串口通信,以提高数据处理效率。\[2\]在串口通信中,接收到的数据会按照循环的方式存储在循环buffer中,当循环buffer存满后,新的数据会从循环buffer的起始位置重新存储,形成一个循环的结构。\[3\]这种循环buffer实现方式可以确保数据的连续性和高效性。 #### 引用[.reference_title] - *1* *2* [Buffer循环机制](https://blog.csdn.net/weixin_45264425/article/details/130233405)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [高效的串口循环Buffer接收处理思路及代码2](https://blog.csdn.net/zz603976046/article/details/121827631)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值