嵌入式应用之FIFO模块原理与实现

FIFO介绍与原理

        FIFO是First-In First-Out的缩写,它是一个具有先入先出特点的缓冲区。FIFO在嵌入式应用的非常广泛,可以说有数据收发的地方,基本就有FIFO的存在。或者为了降低CPU负担,提高数据处理效率,可以在积累到一定的数据量之后,再一次性处理。在嵌入式系统中,FIFO是基于一维数组和结构体实现的循环队列(Queue),或者叫环形队列。可以分为同步FIFO或异步FIO,一般用于数据缓冲,或者不同时钟域之间的数据传递。

FIFO设计中,最重要的满和空的判断条件,需要遵循FIFO读写的两个规则:

●FIFO为空时,不能执行读操作

●FIFO为满时,不能执行写操作

FIFO 代码实现

        使用一维数组来构造一个环形缓冲区,读写地址循环递增,分别实现FIFO初始化、读写操作、判断空满、获取元素个数等函数,并封装成模块。

msgfifo.h

#ifndef __MQUEUE_H__
#define __MQUEUE_H__
#include <stdio.h>
#include <stdint.h>

#define FIFO_SIZE 6
#define qdata_t uint8_t

typedef enum {
    QUEUE_OK,
    QUEUE_FULL,
    QUEUE_EMPTY
}qstatus_t;

typedef struct {
    uint16_t addr_wr;
    uint16_t addr_rd;
    uint16_t length;
    qdata_t fifo[FIFO_SIZE];
}queue_t;

qstatus_t queue_reset(queue_t * q);
qstatus_t queue_read(queue_t *q, qdata_t *pdata);
qstatus_t queue_write(queue_t *q, qdata_t data);
int queue_isFull(queue_t *q);
int queue_isEmpty(queue_t *q);
int queue_print(queue_t *q);

#endif

 msgfifo.c

#include "msgfifo.h"

qstatus_t queue_reset(queue_t * q) {
    int i = 0;
    q->addr_wr = 0;
    q->addr_rd = 0;
    q->length = FIFO_SIZE;

    for(i=0; i<q->length; i++) {
        q->fifo[i] = 0;
    }
    return QUEUE_OK;
}

qstatus_t queue_write(queue_t *q, qdata_t data)
{
    if(queue_isFull(q))
    {
        printf("Write failed(%d), queue is full\n", data);
        return QUEUE_FULL;
    }

    q->fifo[q->addr_wr] = data;
    q->addr_wr = (q->addr_wr + 1) % q->length;
    printf("write success: %02d\n", data);
    queue_print(q);

    return QUEUE_OK;
}

qstatus_t queue_read(queue_t *q, qdata_t *pdata)
{
    if(queue_isEmpty(q))
    {
        printf("Read failed, queue is empty\n");
        return QUEUE_EMPTY;
    }

    *pdata = q->fifo[q->addr_rd];
    q->addr_rd = (q->addr_rd + 1) % q->length;

    printf("read success: %02d\n", *pdata);
    queue_print(q);

    return QUEUE_OK;
}

int queue_isEmpty(queue_t *q)
{
    return (q->addr_wr == q->addr_rd);
}

int queue_isFull(queue_t *q)
{
    return ((q->addr_wr + 1) % q->length == q->addr_rd);
}

int queue_count(queue_t *q)
{
    if(q->addr_rd <= q->addr_wr)
        return (q->addr_wr - q->addr_rd);
    //addr_rd > addr_wr;
    return (q->length + q->addr_wr - q->addr_rd);
}

int queue_print(queue_t *q)
{
    int i = 0;
    int j = 0;

    for(i = 0; i < q->addr_rd; i++)
        printf("     ");

    printf("rd=%d", q->addr_rd);
    printf("\n");

    for(i = 0; i < q->length; i++)
    {
        if(q->addr_wr > q->addr_rd)
        {
            if(i >= q->addr_rd && i < q->addr_wr)
                printf("[%02d] ", q->fifo[i]);
            else
                printf("[  ] ");
        }
        else //addr_rd > addr_wr
        {
            if(i < q->addr_wr || i >= q->addr_rd)
                printf("[%02d] ", q->fifo[i]);
            else
                printf("[  ] ");
        }
    }
    printf("------count = %d\n", queue_count(q));

    for(i = 0; i < q->addr_wr; i++)
        printf("     ");

    printf("wr=%d", q->addr_wr);
    printf("\n");

    return QUEUE_OK;
}

fifotest.c

#include "msgfifo.h"

int main(int argc, char * argv[]){
    queue_t queue;
    qdata_t data;
    qdata_t msgd[8] = {'a','b','c','d', 'e', 'f', 'g'};
    // queue init
    queue_reset(&queue);

    queue_write(&queue, msgd[0]);
    queue_write(&queue, msgd[1]);
    queue_write(&queue, msgd[2]);
    queue_read(&queue, &data);
    queue_read(&queue, &data);

    queue_write(&queue, msgd[3]);
    queue_write(&queue, msgd[4]);
    queue_write(&queue, msgd[5]);
    queue_write(&queue, msgd[6]);
    queue_read(&queue, &data);
    queue_read(&queue, &data);
    queue_read(&queue, &data);

    queue_write(&queue, msgd[1]);
    queue_write(&queue, msgd[3]);
    queue_write(&queue, msgd[5]);
    queue_read(&queue, &data);

    // system("pause");
    return 0;
}

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-06-11 01:32:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-11 01:32:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-11 01:32:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-11 01:32:06       20 阅读

热门阅读

  1. 软件设计师笔记-计算机系统基础知识

    2024-06-11 01:32:06       11 阅读
  2. Reinforcement Learning学习(三)

    2024-06-11 01:32:06       9 阅读
  3. Rust-07-结构体

    2024-06-11 01:32:06       7 阅读
  4. Vue中的组件通信

    2024-06-11 01:32:06       8 阅读
  5. 前端面试题日常练-day62 【面试题】

    2024-06-11 01:32:06       9 阅读
  6. Android RadioButton+GridLayout实现多行多列的单选效果

    2024-06-11 01:32:06       6 阅读
  7. 使用Matplotlib进行Python绘图

    2024-06-11 01:32:06       11 阅读
  8. 构建SOA架构时应该注意的问题

    2024-06-11 01:32:06       8 阅读