Не самая красивая реализация буфера. Мне самому он не нравится, поэтому и выкладываю
Для формирования используется финт ушами из макроса DECLARE_CIRC_BUFFER(). Первый параметр переменная для буфера, второй - размер буфера в байтах. Очень важно чтобы размер был кратен степени двойки, то бишь 4,8,16,32 и т.д. Преимущество данного метода меньше писанины в клиентском коде, из недостатков - накладные расходы на вызов функций и неконстантность SizeMask.
См. также аппаратный уарт
#include "circ_buf.h" #define MY_BUFFER_SIZE (32) #if (MY_BUFFER_SIZE & (MY_BUFFER_SIZE-1)) #error MY_BUFFER_SIZE must be power of 2 #endif DECLARE_CIRC_BUFFER( buf, MY_BUFFER_SIZE ); circ_Init(&buf.b); while( circ_Put( &buf.b, '1' ) != 0 ) continue; print( circ_Get( &buf.b ) );
/** * @file circ_buf.h * @brief Circular Buffer * * @author Rustem Kalimullin * @par E-mail: * hellos@mail.ru * @par Copyright: * (c) Kurt, 2006 */ #ifndef KR_CIRCBUF_INC_H_ #define KR_CIRCBUF_INC_H_ typedef struct circ_buffer_t { volatile unsigned int Get; volatile unsigned int Put; unsigned int SizeMask; unsigned char Buffer[0]; } circ_buffer_t; #define DECLARE_CIRC_BUFFER(name,size) \ struct {\ circ_buffer_t b;\ unsigned char name##pad[ size-0 ];\ } name = { 0, 0, size-1 }; int circ_Get( circ_buffer_t * p ); int circ_Put( circ_buffer_t * p, unsigned char data ); void circ_Init( circ_buffer_t * p ); int circ_HasSpace( circ_buffer_t * p ); int circ_HasData( circ_buffer_t * p ); #endif
/** * @file circ_buf.c * @brief Circular Buffer * * @author Rustem Kalimullin * @par E-mail: * hellos@mail.ru * @par Copyright: * (c) Kurt, 2006 */ #include "common.h" #include "circ_buf.h" //--------------------------------------------------------- //! Get byte from buffer //! @return -1 if failed int circ_Get( circ_buffer_t * p ) { unsigned int t = p->Get; if ( t != p->Put ) { p->Get = t+1 & p->SizeMask; return p->Buffer[t]; } return -1; } //--------------------------------------------------------- //! Put byte to buffer //! @return -1 if failed int circ_Put( circ_buffer_t * p, unsigned char data ) { unsigned int t = p->Put+1 & p->SizeMask; if( t != p->Get ) { p->Buffer[p->Put] = data; p->Put = t; return 0; } return -1; } //--------------------------------------------------------- //! Init buffer void circ_Init( circ_buffer_t * p ) { p->Get = p->Put = 0; } //--------------------------------------------------------- int circ_HasSpace( circ_buffer_t * p ) { unsigned int t = ( (p->Put + 1) & p->SizeMask ); return ( t != p->Get ); } //--------------------------------------------------------- int circ_HasData( circ_buffer_t * p ) { unsigned int t = p->Get; return ( t != p->Put ); }