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_w=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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM