本说明涉及如下内容
- 什么是环形缓冲区
- 如何使用环形缓冲区
- 函数调用说明
- 环形缓冲区源码下载地址https://download.csdn.net/download/xm_smallp/86248489
什么是环形缓冲区
环形缓冲区是一个先进先出(FIFO)的闭环的存储空间。通俗的理解为,在内存中规划了一块“圆形”的地,将该“圆形”进行N(Ring Buffer的大小)等分。如图1,定义了10个数据大小的Buffer,可以间接等效下图右边的环形。另外,环形缓冲区也是队列中的一种。
如何使用环形缓冲区
- 使用环形缓冲区时,定义了两个指针,一个写指针,一个读指针。读指针指向环形缓冲区可读数据的第一个数据地址,写指针指向环形环形缓冲区可写数据的第一个数据地址。如下图,10个数据大小的Buffer,写入了5个数据,其读、写指针指向位置。
- 在进行写操作时,需要先进行判断环形缓冲区是否已写满,若已写满,最直接简单的方式就是直接覆盖原先已写的数据;其次依据实际的应用做相应的处理。
- 在进行读操作时,需要进行判断环形缓冲区是否为空,若为空则无法读取数据。
- 环形缓冲区的核心精华在于对读写指针移动进行取模求余运算,计算出当前的位置,用于判断环形缓冲区当前的状态(空、满),如下图。
- 当Read_Index = Write_Index时,说明环形缓冲区为空。
- 当((Write_Index + 1)% RingBuffer_Size) = Read_Index时,说明环形缓冲区已满。
- 若有多个任务需要读写环形缓冲区时,必须添加互斥保护机制,确保每个任务均正确访问环形缓冲区。
函数调用说明
- 使用枚举定义了环形缓冲区的状态(正常、空、满、一半)。
typedef enum
{
RINGBUFFER_NORMAL,
RINGBUFFER_EMPTY,
RINGBUFFER_FULL,
RINGBUFFER_HALFFULL,
}RingBuffer_State;
- 定义环形缓冲区结构体,包含的信息为:环形缓冲区大小,读、写位置。
typedef struct
{
uint8_t Buff_Ptr[RingBuffSize];
uint16_t Write_Index;
uint16_t Read_Index;
uint16_t Buff_Size;
}RingBuff_Type;
- 初始化环形缓冲区函数,设置读、写位置从0开始,并定义了缓冲区使用的大小,这里默认与环形缓冲区一样。
void RingBuff_Init(void)
{
/*init write and read index*/
RingBuff.Read_Index = 0;
RingBuff.Write_Index = 0;
RingBuff.Buff_Size = RingBuffSize;
}
- 判断环形缓冲区是否为空,若为空,怎返回空的状态,不为空则返回正常状态。
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;
}
- 判断环形缓冲区是否已满,若为满,怎返回满的状态,不为满则返回正常状态。
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;
}
- 环形缓冲区写函数,参数为:要写入的数据和数据长度。
/*
* 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;
}
- 环形缓冲区读函数,参数为:读取的数据及数据长度。
/*
* 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;
}