GodZza

导航

一个RingBuffer(C语言)

也是用于STM32平台下. 通常用于串口通讯缓存.

之前看到一些其他项目写的Buffer缓存. 实在是太不简洁了, 而且还可能有bug.

例如

  当处理数据不够快时, 缓存会直接被覆盖, 而不产生任何提示.

  每次Update都判断 read指针 是否等于 write指针, 是的话又重新将 read和write指针置为数组的开头, 在我看来这是完全没有必要的.( 如果硬要说的话, 可以说是便于调试看数据)

本文仅作简单记录.  代码不是我直接写的, 是我指导同事写的.

 

头文件

#ifndef __RingBuff_H
#define __RingBuff_H

#include <stdint.h>

#define  RINGBUFF_LEN          512     //定义最大接收字节数 200


typedef  struct
{
  volatile uint32_t ReadCount;
  volatile uint32_t WriteCount;
  uint8_t Ring_Buff[RINGBUFF_LEN];
}RingBuff_t;

void RingBuff_Init(RingBuff_t *ringBuff);

//写入RingBuffer缓存

//返回写入字节数

uint32_t RingBuffer_WriteBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length);

 

//读取RingBuffer数据, 并清除在RingBuffer相关的缓存

//返回读取到的字节数

uint32_t RingBuffer_ReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length);

//从RingBuffer中读取一个字节,如果没有读取到内容,则返回-1. int32_t RingBuffer_ReadByte(RingBuff_t
*ringBuff); //-1 0~255
//写入一个字节
int32_t RingBuffer_WriteByte(RingBuff_t *ringBuff,uint8_t byte); //伪读取,因为真的读取的话,会清空读取到的缓存的. 这里是读取到后依然不清除缓存 uint32_t RingBuffer_PseudoReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length); #endif

代码

#include "RingBuff.h"
#include "SEGGER_RTT.h"

void _Assert(int a){
    int x=0;
    while(!a){
        x++;
    }
}
/*防止数组溢出函数*/
int _Repeat(int t, int length)
{
  return t % length;
}
/*获取已经写入的空间*/
int GetReadableSize(RingBuff_t *ringBuff){
    return ringBuff->WriteCount - ringBuff->ReadCount;
}
/*获取可写入空间*/
int GetWritableSize(RingBuff_t *ringBuff)
{
    return RINGBUFF_LEN - GetReadableSize(ringBuff);
}

void RingBuff_Init(RingBuff_t *ringBuff)
{
   //初始化相关信息
   ringBuff->ReadCount = 0;
   ringBuff->WriteCount = 0;
   //ringBuff->Length = 0;
}

/*断言函数 --
参数:结构体指针
数组指针
数据长度
1:判断接收到的数据是否为空,如果为空,返回断言 while(1)
2:判断数据长度是否为空,如果为空,返回断言 while(1)
3:判断接收的数据长度是否大于等于最大的缓存空间,如果是,返回断言 while(1)
*/

static void CheckArguments(RingBuff_t *ringBuff,uint8_t *buffer,  int count){
    _Assert(buffer !=0);
    _Assert(count >=0);
    _Assert(RINGBUFF_LEN >= count);
}

//
static uint32_t Min(uint32_t x,uint32_t y){
    return     x<y ? x:y;
}

/*函数:
RingBuff_t* ringBuff --结构体指针
*buf --指向数据的地址
length -- 写入的长度
*/
uint32_t RingBuffer_WriteBuf(RingBuff_t* ringBuff,uint8_t *buf, uint32_t length){
    uint32_t i=0;
    int writeOffset;
    static uint8_t temp=0;
    
    //断言
    CheckArguments(ringBuff, buf, length);
    //断言:判断接收的数据长度是否已经超过缓存数组中的剩余长度,如果是,返回断言 while(1)
    _Assert(GetWritableSize(ringBuff) >= length);
    for ( i = 0; i < length; ++i)
    {
        writeOffset = _Repeat(ringBuff->WriteCount, RINGBUFF_LEN);
    ringBuff->Ring_Buff[writeOffset] = buf[i];
    ++ringBuff->WriteCount;
        
        if(temp >20){
            temp =0;
            SEGGER_RTT_printf(0,"\r\n");
        }    
        SEGGER_RTT_SetTerminal(1);
        SEGGER_RTT_printf(0,"[%x]",buf[i]);
        temp++;    
        
    }    

    return length;
}
uint32_t RingBuffer_ReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length){
    uint32_t canReadCount=0,i=0;
    int readOffset;
    CheckArguments(ringBuff,buf, length);    

    canReadCount = Min(length, GetReadableSize(ringBuff));

    for ( i = 0; i < canReadCount; ++i)
    {
        readOffset = _Repeat(ringBuff->ReadCount, RINGBUFF_LEN);
        buf[i] = ringBuff->Ring_Buff[readOffset];
        ++ringBuff->ReadCount;
    }
    return canReadCount;
}
/*  函数--读取数据存放到BUF中*/
uint32_t RingBuffer_PseudoReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length){
    uint32_t canReadCount=0,i=0,readCount,readOffset;
    CheckArguments(ringBuff,buf, length);    

    readCount = ringBuff->ReadCount;
    canReadCount = Min(length, GetReadableSize(ringBuff));
    
    for ( i = 0; i < canReadCount; ++i)
    {
        readOffset = _Repeat(readCount, RINGBUFF_LEN);
        buf[i] = ringBuff->Ring_Buff[readOffset];
        ++readCount;
    }
    return canReadCount;
}


int32_t RingBuffer_ReadByte(RingBuff_t *ringBuff){
    uint8_t val;
    uint32_t readed = RingBuffer_ReadBuf(ringBuff,&val,1);
    if(readed ==0)
        return -1;
    return val;
}

/*
函数:串口接收到的一个字节,写入到buf中
参数: RingBuff_t *ringBuff--结构体指针
            byte -- 写入的数据
返回--uint32_t ret
*/
int32_t RingBuffer_WriteByte(RingBuff_t *ringBuff,uint8_t byte){
    uint32_t ret = RingBuffer_WriteBuf(ringBuff,&byte,1);
    return ret;
}

 

posted on 2021-07-26 19:24  GodZza  阅读(684)  评论(0编辑  收藏  举报