RingBuffer循环缓冲区的应用

一.背景描述

        在项目中用到了编码器功能,编码器的报文发送周期是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次,没有出现丢帧的现象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值