FIFO缓存区原理

1.缓存区的制作

  思路:按照输入数据的顺序输出数据

简单地数据存储:

struct FIFO_BUF{
          unsigned char data[32];
          int next;  
}fifo_buf;

unsigned char buffer[32]={0};

void init_write_to_buf(void)
{
         if(fifo_buf.next<32)
        {
                fifo_buf.data[fifo_buf.next]=buffer[fifo_buf.next];   //将buffer中的数据写入到fifo_buf中;
                fifo_buf.next++;
        }
        return 0;
}

  fifo_buf.next的起始点是0,所以最初存储的数据是fifo_buf.data[0],下一个是fifo_buf.data[1],依次类推,一共32个存储位置。

  下一个存储位置有用变量next管理,这样就可以记住32数据而不溢出,为保险next变为32之后就不要了

简单地数据读取:

void read_from_fifo_buf(void)
{
        for(;;)
       {
               if(fifo_buf.next==0)
                       return;      //为0表示没有数据,不用读取
              else
              {
                       i = fifo_buf.data[0];   //读取第0个位置的元素;
                       fifo_buf.next--;
                      for(int j=0;j<fifo_buf.next;j++)
                      {
                              fifo_buf.data[j] = fifo_buf.data[j+1];
                      }
              }
       }
}

  如果next不是0,说明至少有一个数据,最开始的一个数据肯定放在data[0]中,将这个数据放入到变量i中,这样数据就减少了一个,所以next要减去1;

  接下来的for语句工作原理如下:

  

  数据存放的位置全部都向前移动了一个位置。如果不移送的话,下次就不能从data[0]读入数据了。

  此方法的缺点:移送数据的处理,一般不会超过3个,且基本上没问题。有时需要移送上百个数据,就会出现问题。

2 改善上述缓存区

  思路:不仅要维护下一个要写入数据的位置,还要维护下一个要读出数据的位置。这就好像数据读出位置追着数据写入位置跑一样。这样就不需要数据移送操作了。数据读出位置追上数据写入位置的时候,就相当于缓存区为空,没有数据。

  但是这样的缓存区使用一段时间后,下一个数据写入位置会变为31,而这时下一个数据读出位置可能已经是29或者30了。当下一个写入位置变为32的时候,就没地方可以写入数据了。

  如果当下一个数据写入位置到达缓存区终点时,数据读出位置也恰好到达缓冲区终点,也就是缓冲区正好变为空,这种情况我们只要将下一个数据写入位置和下一个数据读出位置都再置位0就行了,就像转回去从头再来一样。

  但是总还是会有数据读出位置没有追上数据写入位置的情况。这时又不得不进行数据移送操作。

3 缓存区的实现

  当下一个数据写入位置到达缓冲区最末尾时,缓存区开头部分应该已经变空了(如果还没有变空,说明数据读出跟不上数据写入,只能把部分数据扔掉了)。因此如果下一个数据写入位置到了32以后,就强制性的将它设置为0。这样写一个数据写入位置就跑到了下一个数据读出位置的后面。

  对下一个数据读出位置也做同样的处理。一旦到了32以后,就把它设置为从0开始继续读取数据。这样32字节的缓存区就能一圈一圈地不停循环,长久使用。数据移送操作一次都不需要。这个缓存区虽然只有32字节,只要不溢出的话,他就能持续使用下去。

数据的写入

struct FIFO_BUF{
        unsigned char data[32];
        int next_w;       //写位置标志
        int next_r;        //读位置标志
        int len;             //数据长度
}fifo_buf;
void write_to_fifo_buf(void)
{
        if(fifo_buf.len>=32)
                return;
        else
       {
               fifo_buf.data = data;     //将一个数据写入到缓存中
               fifo_buf.next_w++;
               fifo_buf.len++;
               if(fifo_buf.next_w==32)
                     fifo_buf.next=0;
       }
       return 0;
}

数据的读取

void read_from_fifo_buf(void)
{
        for(;;)
       {
               i = fifo_buf.data[fifo_buf.next_r];   //读取next_r处的数据
              fifo_buf.len--;
              fifo_buf.next_r++;
              if(fifo_buf.next_r==32)
              {
                      fifo_buf.next_r=0;
              }
       }
}

4 FIFO缓存区最终实现

struct FIFO_BUF
{
        unsigned char *buf;
        int fifo_w;
        int fifo_r;
        int len;     //缓存区总的字节数
        int free;    //用于保存缓存区里没有数据的字节数
        int flags;
}fifo_buf;

初始化

void fifo_init(fifo_buf *fifo,int len,unsigned char *buf)
{
        fifo->buf = buf;
        fifo->len = len;
        fifo->free = len;
        fifo->fifo_w = 0;
        fifo->fifo_r = 0;
        fifo->flags = 0;
        return;
}

#define FLAGS_OVERRUN 0x0001

int fifo_write(struct fifo_buf *fifo,unsigned char data)
{
        if(fifo->free == 0) //空余没有了,溢出
        {
                fifo->flags |= FLAGS_OVERRUN;
                return -1;
        }
        fifo->buf[fifo->fifo_w]=data;
        fifo->fifo_w++;
        if(fifo->w==fifo->len)
       {
               fifo->w = 0;
       }
       fifo->free--;
       return 0;
}

int fifo_read(fifo_buf *fifo,unsigned char buffer)
{
        if(fifo->free == fifo->len)
        {
                return -1;
        }
       else
       {
                buffer = fifo->buf[fifo->fifo_r];    //一个数据写入到buffer中
                fifo->fifo_r++;
                if(fifo->fifo_r==32)
                {
                        fifo->fifo_r = 0;
                }
                fifo->free++;
       }
       return buffer;
}

查询写入了多少数据

int fifo_status(void)
{
        return fifo->len - fifo->free;
}

猜你喜欢

转载自www.cnblogs.com/dongry/p/11144358.html
今日推荐