环形队列在嵌入式开发上有较多的应用,比如任务队列,串行数据缓存等等。使用环形队列可以实现更高效的数据管理。代码实现如下:
typedef struct {
uint8_t* buf; //指向队列数组的指针
uint16_t maxsize;
uint16_t length; //长度
uint16_t head; //队头
uint16_t tail; //队尾
uint16_t fill_cnt; //队列计数
uint16_t clear; //缓冲区复位
}bytebuffer_def;
/**
* @brief 循环队列初始化
* @param None
* @retval None
*/
bytebuffer_def bytebuffer_init(void* buf, uint16_t size)
{
bytebuffer_def q;
q.buf = buf;
q.maxsize = size;
q.fill_cnt = q.head = q.tail = 0;
return q;
}
/**
* @brief 写入缓存数据
* @param None
* @retval None
*/
uint16_t bytebuf_write(bytebuffer_def* q, uint16_t dat)
{
/*储存区满*/
if (((q->tail + 1) % q->maxsize) == q->head) {
return false;
}
q->buf[q->tail] = dat;
q->tail++;
q->tail = q->tail % q->maxsize;
q->fill_cnt++;
return true;
}
/**
* @brief 读取缓冲区数据
* @param
* @retval None
*/
uint16_t bytebuf_read(bytebuffer_def* q, uint16_t* dat)
{
if (dat == NULL || q->fill_cnt == 0) {
return false;
}
*(dat) = q->buf[q->head];
q->head++;
q->head = q->head % q->maxsize;
q->fill_cnt--;
return true;
}
/**
* @brief 删除缓冲区数据
* @param
* @retval None
*/
uint16_t bytebuf_pop(bytebuffer_def* q, uint16_t length)
{
if (length > q->fill_cnt) {
return false;
}
if ((q->head + length) < q->maxsize) {
q->head += length;
}
else {
q->head = length - (q->maxsize - q->head);
}
q->fill_cnt -= length;
return true;
}
/**
* @brief 查询缓冲区数据
* @note 该操作不会读取缓冲区数据
* @param None
* @retval None
*/
uint16_t bytebuf_query(bytebuffer_def* q, uint16_t* dat, uint16_t length)
{
if (dat == NULL || length > q->fill_cnt) {
return false;
}
uint16_t i;
uint16_t query_head;
query_head = q->head;
for (i = 0; i < length; i++) {
*(dat + i) = q->buf[query_head];
query_head++;
query_head = query_head % q->maxsize;
}
return true;
}
/**
* @brief 清除缓冲区
* @param None
* @retval None
*/
void clear_bytebuf(bytebuffer_def* q)
{
q->tail = q->head;
q->fill_cnt = 0;
}
应用简单举例:
uint8_t fifo[10];
bytebuffer_def bytebuffer;
int main()
{
uint8_t read_dat;
/*初始化环形队列*/
bytebuffer = bytebuffer_init(fifo, 10);
/*写入数据*/
bytebuf_write(&bytebuffer, 1);
bytebuf_write(&bytebuffer, 2);
bytebuf_write(&bytebuffer, 3);
/*读取1个数据*/
bytebuf_read(&bytebuffer, &read_dat);
return 0;
}