环形缓冲区(Ring Buffer)使用说明

本说明涉及如下内容

什么是环形缓冲区

环形缓冲区是一个先进先出(FIFO)的闭环的存储空间。通俗的理解为,在内存中规划了一块“圆形”的地,将该“圆形”进行N(Ring Buffer的大小)等分。如图1,定义了10个数据大小的Buffer,可以间接等效下图右边的环形。另外,环形缓冲区也是队列中的一种。
在这里插入图片描述

如何使用环形缓冲区

  1. 使用环形缓冲区时,定义了两个指针,一个写指针,一个读指针。读指针指向环形缓冲区可读数据的第一个数据地址,写指针指向环形环形缓冲区可写数据的第一个数据地址。如下图,10个数据大小的Buffer,写入了5个数据,其读、写指针指向位置。在这里插入图片描述
  2. 在进行写操作时,需要先进行判断环形缓冲区是否已写满,若已写满,最直接简单的方式就是直接覆盖原先已写的数据;其次依据实际的应用做相应的处理。
  3. 在进行读操作时,需要进行判断环形缓冲区是否为空,若为空则无法读取数据。
  4. 环形缓冲区的核心精华在于对读写指针移动进行取模求余运算,计算出当前的位置,用于判断环形缓冲区当前的状态(空、满),如下图。
    在这里插入图片描述
  5. 当Read_Index = Write_Index时,说明环形缓冲区为空。
  6. 当((Write_Index + 1)% RingBuffer_Size) = Read_Index时,说明环形缓冲区已满。
  7. 若有多个任务需要读写环形缓冲区时,必须添加互斥保护机制,确保每个任务均正确访问环形缓冲区。

函数调用说明

  1. 使用枚举定义了环形缓冲区的状态(正常、空、满、一半)。
typedef enum 
{
    RINGBUFFER_NORMAL,
    RINGBUFFER_EMPTY,		    
    RINGBUFFER_FULL,			
    RINGBUFFER_HALFFULL,		
}RingBuffer_State;
  1. 定义环形缓冲区结构体,包含的信息为:环形缓冲区大小,读、写位置。
typedef struct
{
    uint8_t  Buff_Ptr[RingBuffSize];         
    uint16_t Write_Index;     
    uint16_t Read_Index;        
    uint16_t Buff_Size;        
}RingBuff_Type;
  1. 初始化环形缓冲区函数,设置读、写位置从0开始,并定义了缓冲区使用的大小,这里默认与环形缓冲区一样。
void RingBuff_Init(void)
{
    /*init write and read index*/
    RingBuff.Read_Index  = 0;
    RingBuff.Write_Index = 0;
    RingBuff.Buff_Size = RingBuffSize;
}
  1. 判断环形缓冲区是否为空,若为空,怎返回空的状态,不为空则返回正常状态。
RingBuffer_State RingBuff_Empty(void)
{
    RingBuffer_State status = RINGBUFFER_NORMAL;   
    /*ringbuff is empty ???*/
    if(RingBuff.Read_Index == RingBuff.Write_Index)
    {
        status = RINGBUFFER_EMPTY;
        
        #ifdef RingBuffDebug
        printf("ringbuff is empty \r\n");
        #endif
    }
    return status;
}
  1. 判断环形缓冲区是否已满,若为满,怎返回满的状态,不为满则返回正常状态。
RingBuffer_State RingBuff_Full(void)
{
    RingBuffer_State status = RINGBUFFER_NORMAL;   
    /*ringbuff is full ???*/
    if(((RingBuff.Write_Index + 1) % RingBuff.Buff_Size) == RingBuff.Read_Index)
    {
        status = RINGBUFFER_FULL;
        #ifdef RingBuffDebug
        printf("ringbuff is full \r\n");
        #endif
    }
    return status;
}
  1. 环形缓冲区写函数,参数为:要写入的数据和数据长度。
/*
* length : write data length
* prt    : buffer prt
*/
uint16_t RingBuff_Write(uint8_t *ptr, uint16_t length)
{
    RingBuffer_State status = RINGBUFFER_NORMAL;  
    /*get ringbuff status */
    status = RingBuff_Full();

    if (status == RINGBUFFER_FULL)
    {
        return 0;
    }
    else
    {
        /*copy ptr data into ringbuff */
        memcpy(&RingBuff.Buff_Ptr[RingBuff.Write_Index], ptr, length);
        
        /*write index cnt*/
        RingBuff.Write_Index = (RingBuff.Write_Index+1)%RingBuff.Buff_Size;
        
        /*return write index val*/
        return RingBuff.Write_Index;       
    }
    return 0;
}
  1. 环形缓冲区读函数,参数为:读取的数据及数据长度。
/*
* length : read data length
* prt    : buffer prt
*/
uint16_t RingBuff_Read(uint8_t *ptr, uint16_t length)
{
    RingBuffer_State status = RINGBUFFER_NORMAL;  
    /*get ringbuff status */
    status = RingBuff_Empty();    

    if(status == RINGBUFFER_EMPTY)
    {
        return 0;
    }
    else
    {
        /*copy ringbuff data to ptr*/
        memcpy(ptr, &RingBuff.Buff_Ptr[RingBuff.Read_Index],length);
        #ifdef RingBuffDebug
        for (uint8_t i = 0; i < length; i++)
        {
            printf("readdata=%d,\r\n",ptr[i]);
        }
        #endif
        /*read index cnt*/
        RingBuff.Read_Index = (RingBuff.Read_Index+1)%RingBuff.Buff_Size;

        /*return read index*/
        return RingBuff.Read_Index;
    }
    return 0;
}

  • 11
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Ring Buffer环形缓冲区)是一种循环使用的缓冲区,常用于实现数据的异步传输。下面是一个简单的C语言实现环形缓冲区的代码示例。 ```c #include <stdio.h> #include <stdlib.h> #define BUFFER_SIZE 10 typedef struct { int *buffer; int head; int tail; int size; } RingBuffer; RingBuffer *create_ring_buffer(int size) { RingBuffer *rb = (RingBuffer *)malloc(sizeof(RingBuffer)); rb->buffer = (int *)calloc(size, sizeof(int)); rb->head = 0; rb->tail = 0; rb->size = size; return rb; } void destroy_ring_buffer(RingBuffer *rb) { free(rb->buffer); free(rb); } int is_empty(RingBuffer *rb) { return rb->head == rb->tail; } int is_full(RingBuffer *rb) { return (rb->tail + 1) % rb->size == rb->head; } void push(RingBuffer *rb, int value) { if (is_full(rb)) { printf("Ring buffer is full!\n"); return; } rb->buffer[rb->tail] = value; rb->tail = (rb->tail + 1) % rb->size; } int pop(RingBuffer *rb) { if (is_empty(rb)) { printf("Ring buffer is empty!\n"); return -1; } int value = rb->buffer[rb->head]; rb->head = (rb->head + 1) % rb->size; return value; } int main() { RingBuffer *rb = create_ring_buffer(BUFFER_SIZE); push(rb, 1); push(rb, 2); push(rb, 3); printf("Pop: %d\n", pop(rb)); printf("Pop: %d\n", pop(rb)); push(rb, 4); push(rb, 5); push(rb, 6); while (!is_empty(rb)) { printf("Pop: %d\n", pop(rb)); } destroy_ring_buffer(rb); return 0; } ``` 在这个示例中,我们定义了一个RingBuffer结构体,包含了一个整型数组作为缓冲区、头指针、尾指针和缓冲区大小。我们通过create_ring_buffer函数创建缓冲区,并通过destroy_ring_buffer函数销毁缓冲区。 我们还定义了is_empty和is_full函数用于判断缓冲区是否为空或已满,以及push和pop函数用于向缓冲区中添加或取出数据。 在main函数中,我们先向缓冲区中添加了三个整数,然后取出了前两个。接着,我们又向缓冲区中添加了三个整数,并通过while循环将缓冲区中的所有数据取出并打印。最后,我们销毁了缓冲区。 这个示例只是一个简单的实现,实际的环形缓冲区可能会更加复杂。但是,这个示例可以帮助你了解如何使用C语言实现环形缓冲区

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值