一.背景描述
在项目中用到了编码器功能,编码器的报文发送周期是40ms,如果滚动编码器的速度过快就会出现丢帧的问题,为了解决该问题在代码中引入了Ring buffer。
二.代码实现
/*Ringbuffer structural define*/
typedef struct {
uint8_t *buffer_ptr; /*point to a array, used for save data*/
uint16_t read_index; /*used for read data from ring buffer*/
uint16_t write_index; /*used for write data to ring buffer*/
uint16_t buffer_size; /*define the size of ring buffer*/
uint16_t buffer_length; /*the length of ring buffer which have been used*/
}RingBuffer_TypeDef;
/*the status of ring buffer*/
typedef enum {
RINGBUFFER_EMPTY, /*ring buffer is empty*/
RINGBUFFER_FULL, /*ring buffer is full*/
RINGBUFFER_HALFFULL, /* half full is neitherfull nor empty */
}RingBuffer_State ;
RingBuffer_TypeDef EncodeRingBUffer;
uint8_t EcoderBuffer[ENCODER_RINGBUFFER_SIZE] = {0};
/**
* @brief IGet the ringbuffer buffer status.
*
* @param rb A pointer to the ring buffer object.
*
* @return Return the status.
*/
RingBuffer_State ringbuffer_status(RingBuffer_TypeDef *rb)
{
if (rb->buffer_length == rb->buffer_size) {
return RINGBUFFER_FULL;
} else if (rb->buffer_length == 0) {
return RINGBUFFER_EMPTY;
} else {
return RINGBUFFER_HALFFULL;
}
}
/**
* @brief Get the ringbuffer buffer remain to read.
*
* @param rb A pointer to the ring buffer object.
*
* @return ringbuffer buffer remain to read.
*/
uint16_t ringbuffer_length(RingBuffer_TypeDef *rb)
{
return rb->buffer_length;
}
/**
* @brief Initialize the ring buffer object.
*
* @param rb A pointer to the ring buffer object.
* @param pool A pointer to the buffer.
* @param size The size of the buffer in bytes.
*
* @return Return the status.
*/
int8_t ringbuffer_init(RingBuffer_TypeDef *rb,uint8_t *pool,int16_t size)
{
if(rb == NULL) {
return -1;
}
if(size == 0) {
return -1;
}
/* initialize read and write index */
rb->read_index = 0;
rb->write_index = 0;
/* set buffer pool and size */
rb->buffer_ptr = pool;
rb->buffer_size = size;
rb->buffer_length = 0;
return 1;
}
/**
* @brief Put the data into the ring buffer
*
* @param rb A pointer to the ring buffer object.
* @param Data the data need write to buffer.
*
* @return Return the status.
*/
int8_t ringbuffer_put(RingBuffer_TypeDef *rb,uint8_t Data)
{
if(rb == NULL) {
return -1;
}
/* no space */
if (ringbuffer_status(rb) == RINGBUFFER_FULL){
return -1;
}
rb->buffer_ptr[rb->write_index] = Data;
rb->write_index = (rb->write_index + 1) % rb->buffer_size;
rb->buffer_length++;
return 1;
}
/**
* @brief Get the data in the ring buffer.
*
* @param rb The pointer to the ring buffer object.
* @param ptr A pointer to the data buffer.
*
* @return Return the status.
*/
int8_t ringbuffer_get(RingBuffer_TypeDef *rb,uint8_t *ptr)
{
if(rb == NULL) {
return -1;
}
/* no data */
if (ringbuffer_status(rb) == RINGBUFFER_EMPTY) {
return -1;
}
*ptr = rb->buffer_ptr[rb->read_index];
rb->read_index = (rb->read_index + 1) % rb->buffer_size;
rb->buffer_length--;
return 1;
}
三.验证
如上图所示,示波器抓取到编码器滚动了9次(该编码器一次边沿跳变认为是一次有效信号),CANoe检测到该编码器信号也发送了9次,没有出现丢帧的现象。