元件 通用環形緩衝區模組

2021-08-14 02:14:49 字數 3818 閱讀 2374

寫在前面

1.基本原則

先進先出(fifo),重複使用。

2.實現原理

環形緩衝區,顧名思義就是一段迴圈使用的一段記憶體。通過寫指標向「空白記憶體」(未寫入過或者已經被讀出的記憶體)寫入資料並記錄,讀指標從已寫的記憶體讀取資料並記錄,當指標訪問到記憶體最後乙個位置時,再折回第乙個記憶體位置,達到迴圈效果。

3.注意事項

1)環形緩衝區本質是「生產者消費者」模型,必須先有生產(寫)後有消費(讀),不可提前消費(讀);

2)注意程式效率問題,如果讀效率過低,導致「生產」過剩,從而覆蓋未讀出的資料,導致出錯,此時需增加環形緩衝區記憶體大小或者優化**效率;

3)單一執行緒訪問時是安全的,多執行緒訪問時,為保證資料安全性必須加互斥鎖機制;

4.應用場合

處理串列埠(rs232)接收資料命令:

串列埠中斷--->資料接收--->寫入環形緩衝區--->資料處理執行緒讀取環形緩衝區--->處理有效資料。

5.實現方式

標頭檔案

#ifndef _fifo_h_

#define _fifo_h_

#include #include typedef void (*lock_fun)(void);

typedef struct

_fifo_t;

extern void fifo_register(_fifo_t *pfifo, uint8_t *pfifo_buf, uint32_t size,

lock_fun lock, lock_fun unlock);

extern void fifo_release(_fifo_t *pfifo);

extern uint32_t fifo_write(_fifo_t *pfifo, const uint8_t *pbuf, uint32_t size);

extern uint32_t fifo_read(_fifo_t *pfifo, uint8_t *pbuf, uint32_t size);

extern uint32_t fifo_get_total_size(_fifo_t *pfifo);

extern uint32_t fifo_get_free_size(_fifo_t *pfifo);

extern uint32_t fifo_get_occupy_size(_fifo_t *pfifo);

#endif

原始檔

#include #include "fifo.h"

/** * @brief 註冊乙個fifo

* @param pfifo: fifo結構體指標

pfifo_buf: fifo記憶體塊

size: 長度

* @retval none

*/void fifo_register(_fifo_t *pfifo, uint8_t *pfifo_buf, uint32_t size,

lock_fun lock, lock_fun unlock)

/*** @brief 釋放fifo

* @param pfifo: fifo結構體指標

* @retval none

*/void fifo_release(_fifo_t *pfifo)

/*** @brief 往fifo寫資料

* @param pfifo: fifo結構體指標

pbuf: 待寫資料

size: 待寫資料大小

* @retval 實際寫大小

*/uint32_t fifo_write(_fifo_t *pfifo, const uint8_t *pbuf, uint32_t size)

free_size = fifo_get_free_size(pfifo);

if(free_size == 0)

if(free_size < size)

w_size = size;

if (pfifo->lock != null)

pfifo->lock();

while(w_size-- > 0)

pfifo->occupy_size++;

}if (pfifo->unlock != null)

pfifo->unlock();

return size;}

/** * @brief 從fifo讀資料

* @param pfifo: fifo結構體指標

pbuf: 待讀資料快取

size: 待讀資料大小

* @retval 實際讀大小

*/uint32_t fifo_read(_fifo_t *pfifo, uint8_t *pbuf, uint32_t size)

occupy_size = fifo_get_occupy_size(pfifo);

if(occupy_size == 0)

if(occupy_size < size)

if (pfifo->lock != null)

pfifo->lock();

r_size = size;

while(r_size-- > 0)

pfifo->occupy_size--;

}if (pfifo->unlock != null)

pfifo->unlock();

return size;}

/** * @brief 獲取fifo空間大小

* @param pfifo: fifo結構體指標

* @retval fifo大小

*/uint32_t fifo_get_total_size(_fifo_t *pfifo)

/*** @brief 獲取fifo空閒空間大小

* @param pfifo: fifo結構體指標

* @retval 空閒空間大小

*/uint32_t fifo_get_free_size(_fifo_t *pfifo)

/*** @brief 獲取fifo已用空間大小

* @param pfifo: fifo結構體指標

* @retval fifo已用大小

*/uint32_t fifo_get_occupy_size(_fifo_t *pfifo)

其中,注意點是環形緩衝區「滿」與「空」狀態處理,這裡使用了讀、寫指標的「翻轉」標識,即當讀、寫指標訪問到緩衝區最後位址時,訪問位址折回初始位址,此時做乙個翻轉標識;當讀位址和寫位址相等時,如果讀、寫翻轉標識相等,說明此時緩衝區為「空狀態」,否則緩衝區為「滿」狀態。

5.應用例子

註冊乙個512位元組大小環形緩衝區,然後往緩衝區寫入資料,接著讀出來。

#include "fifo.h"

static uint8_t buf_0[512];

static _fifo_t fifo_0;

int main(void)

; uint8_t r_data[10];

fifo_register(&fifo_0, buf_0, sizeof(buf_0), 0, 0);

fifo_write(&fifo_0, (const uint8_t*)w_data, sizeof(data));

fifo_read(&fifo_0, r_data, 1);

fifo_read(&fifo_0, &r_data[1], 2);

return 0;

}

環形緩衝區

include include include include include define buffsize 1024 1024 define min x,y x y x y pthread mutex t lock pthread mutex initializer struct cycle b...

環形緩衝區

define print buf size 16 1024 static char g pcnetprintbuf 環形緩衝區的首位址 static int g ireadpos 0 環形緩衝區讀的位置 static int g iwritepos 0 環形緩衝區寫的位置 intinit 判斷環形緩...

環形緩衝區

環形緩衝區要維護兩個索引,分別對應寫入端 w 和讀取端 r 寫入 push 的時候,先確保環沒滿,然後把資料複製到 w 所對應的元素,最後 w 指向下乙個元素 讀取 pop 的時候,先確保環沒空,然後返回 r 對應的元素,最後 r 指向下乙個元素。上述的操作並不複雜,不過有乙個小小的麻煩 空環和滿環...