嵌入式常用模块——环形队列(2)

文章目录

    • 前言
    • 介绍
    • 实现

前言

指针是一个好东西 也是一个相对来说麻烦和危险的家伙。在使用环形队列时候,如果每次接收数据的长度变化不大的时候。可以用二维数组方式来实现环形队列,从而减少一些指针操作。

介绍

使用这个队列,你需要定义你的数据块结构。然后初始化队列时候把其强制转换为uint8_t。
然后根据你需求确定个数。
这样实现就像一个二维数组了,第一维是数据块结构长度,第二维是个数。然后根据第二维的下标循环使用一个个一维空间。这样做相比于上一篇,减少了很多指针。实现上也简单。但是因为每个数据快等长。所以不适用于长度变化较大的情况,那样会浪费很多空间。

struct ring_buffer_t {
    volatile uint8_t *buffer;   //数据块指针
    unsigned element_size;      //数据块大小
    unsigned element_count;     //数据块个数
    volatile unsigned head;     //头下标
    volatile unsigned tail;     //尾下标
};

实现

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
struct ring_buffer_t {
    volatile uint8_t *buffer;   //数据块指针
    unsigned element_size;      //数据块大小
    unsigned element_count;     //数据块个数
    volatile unsigned head;     //头下标
    volatile unsigned tail;     //尾下标
};
typedef struct ring_buffer_t RING_BUFFER;
unsigned ringBufCount(RING_BUFFER const *b)
{
    unsigned head, tail;
    if (b) {
        head = b->head;
        tail = b->tail;
        return head - tail;
    }
    return 0;
}
bool ringBufFull(RING_BUFFER const *b)
{
    return (b ? (ringbufCount(b) == b->element_count) : true);
}
bool ringBufEmpty(RING_BUFFER const *b)
{
    return (b ? (ringbufCount(b) == 0) : true);
}
volatile uint8_t *ringBufPopFront(RING_BUFFER * b)
{
    volatile uint8_t *data_element = NULL;

    if (!ringbufEmpty(b)) {
        data_element = b->buffer;
        data_element += ((b->tail % b->element_count) * b->element_size);
        b->tail++;
    }
    return data_element;
}
bool ringBufPut(RING_BUFFER * b,uint8_t * data_element)
{
    bool status = false;
    volatile uint8_t *ring_data = NULL;
    unsigned i;
    if (b && data_element) {
        if (!ringbufFull(b)) {
            ring_data = b->buffer;
            ring_data += ((b->head % b->element_count) * b->element_size);
            for (i = 0; i < b->element_size; i++) {
                ring_data[i] = data_element[i];
            }
            b->head++;
            status = true;
        }
    }
    return status;
}
volatile uint8_t *ringBufAlloc(
    RING_BUFFER * b)
{
    volatile uint8_t *ring_data = NULL;
    if (b) {
        if (!ringbufFull(b)) {
            ring_data = b->buffer;
            ring_data += ((b->head % b->element_count) * b->element_size);
            b->head++;
        }
    }
    return ring_data;
}
void ringBufInit(RING_BUFFER * b,uint8_t * buffer,unsigned elementsize, unsigned elementcount)
{
    if (b) 
    {
        b->head = 0;
        b->tail = 0;
        b->buffer = buffer;
        b->element_size = elementsize;
        b->element_count = elementcount;
    }
    return;
}

你可能感兴趣的:(stm32)