一个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; }