优雅地用宏实现环形缓冲区
之前寫的環(huán)行緩沖區(qū)文章
柔性數(shù)組和環(huán)形隊列之間的故事
C語言,環(huán)形隊列
循環(huán)緩沖區(qū)是嵌入式軟件工程師在日常開發(fā)過程中的關(guān)鍵組件。
多年來,互聯(lián)網(wǎng)上出現(xiàn)了許多不同的循環(huán)緩沖區(qū)實現(xiàn)和示例。我非常喜歡這個模塊,可以GitHub上找到這個開源的 CBUF.h 模塊。
地址:https://github.com/barraq/BRBrain/blob/master/firmware/CBUF.h
CBUF.h 模塊使用宏實現(xiàn)循環(huán)緩沖區(qū),具體源碼如下所示;
#if?!defined(?CBUF_H?) #define?CBUF_H???????/**<?Include?Guard??????????????????????????*//*?----?Include?Files?----------------------------------------------------?*//*?----?Constants?and?Types?----------------------------------------------?*//** *???Initializes?the?circular?buffer?for?use. */?#define?CBUF_Init(?cbuf?)???????cbuf.m_getIdx?=?cbuf.m_putIdx?=?0/** *???Returns?the?number?of?elements?which?are?currently?contained?in?the?*??circular?buffer. */#define?CBUF_Len(?cbuf?)????????((typeof(?cbuf.m_putIdx?))((?cbuf.m_putIdx?)?-?(?cbuf.m_getIdx?)))/** *???Appends?an?element?to?the?end?of?the?circular?buffer */#define?CBUF_Push(?cbuf,?elem?)?(cbuf.m_entry)[?cbuf.m_putIdx++?&?((?cbuf##_SIZE?)?-?1?)]?=?(elem)/** *???Retrieves?an?element?from?the?beginning?of?the?circular?buffer */#define?CBUF_Pop(?cbuf?)????????(cbuf.m_entry)[?cbuf.m_getIdx++?&?((?cbuf##_SIZE?)?-?1?)]/** *???Retrieves?the?i'th?element?from?the?beginning?of?the?circular?buffer */#define?CBUF_Get(?cbuf,?idx?)????????(cbuf.m_entry)[(?cbuf.m_getIdx?+?idx?)?&?((?cbuf##_SIZE?)?-?1?)]/** *???Retrieves?the?i'th?element?from?the?end?of?the?circular?buffer */#define?CBUF_GetEnd(?cbuf,?idx?)????????(cbuf.m_entry)[(?cbuf.m_putIdx?-?idx?-?1?)?&?((?cbuf##_SIZE?)?-?1?)]/** *???Determines?if?the?circular?buffer?is?empty */#define?CBUF_IsEmpty(?cbuf?)????(?CBUF_Len(?cbuf?)?==?0?)/** *???Determines?if?the?circular?buffer?is?full. */#define?CBUF_IsFull(?cbuf?)?????(?CBUF_Len(?cbuf?)?==?(?cbuf##_SIZE?))/** *???Determines?if?the?circular?buffer?is?currenly?overflowed?or?underflowed. */#define?CBUF_Error(?cbuf?)??????(?CBUF_Len(?cbuf?)?>?cbuf##_SIZE?)#if?defined(?__cplusplus?)template?<?class?IndexType,?unsigned?Size,?class?EntryType?> class?CBUF { public:CBUF(){m_getIdx?=?m_putIdx?=?0;}IndexType?Len()?const???{?return?m_putIdx?-?m_getIdx;?}bool?IsEmpty()?const????{?return?Len()?==?0;?}bool?IsFull()?const?????{?return?Len()?==?Size;?}bool?Error()?const??????{?return?Len()?>?Size;?}void?Push(?EntryType?val?)???{m_entry[?m_putIdx++?&?(?Size?-?1?)]?=?val;}EntryType?Pop(){return?m_entry[?m_getIdx++?&?(?Size?-?1?)];}private:volatile?IndexType??m_getIdx;volatile?IndexType??m_putIdx;EntryType???????????m_entry[?Size?];};#endif??//?__cplusplus/*?----?Variable?Externs?-------------------------------------------------?*/ /*?----?Function?Prototypes?----------------------------------------------?*//**?@}?*/#endif?//?CBUF_H現(xiàn)在一般我不喜歡以這種方式使用宏,但實現(xiàn)已被證明是快速、高效且工作相對良好的,這是很難爭論的。
循環(huán)緩沖區(qū)的設(shè)置非常簡單。首先,需要定義循環(huán)緩沖區(qū)的大小。這是通過定義宏 myQ_SIZE 來完成的,同時記住緩沖區(qū)大小需要是 2 的冪。
然后通過創(chuàng)建一個 myQ 類型的變量來聲明循環(huán)緩沖區(qū)。例如,如果 myQ_SIZE 定義為 64 字節(jié),則可以定義 UART 的發(fā)送和接收緩沖區(qū),如下面的圖 1 所示。
圖 1 – 定義循環(huán)緩沖區(qū)在此示例中,myQ 被定義為靜態(tài)以限制緩沖區(qū)的范圍并聲明為易失性,因為它們在中斷內(nèi)被修改。定義循環(huán)緩沖區(qū)只是第一步。為了分配緩沖區(qū),必須將這些變量傳遞給 CBUF_INIT 宏,如下圖 2 所示。
圖 2 – 緩沖區(qū)初始化除了這個初始設(shè)置之外,緩沖區(qū)相當簡單且易于使用。例如,可以使用 CBUF_PUSH 將通過串行接口接收 UART接收的字符推送到循環(huán)緩沖區(qū),如圖 3 所示。
圖 3 – 推入緩沖區(qū)開發(fā)人員不僅希望將數(shù)據(jù)推送到循環(huán)緩沖區(qū)上,還希望從緩沖區(qū)彈出或獲取數(shù)據(jù)。看到這一點的一個簡單示例是需要獲取字符并通過 UART 傳輸?shù)拇邪l(fā)送器。圖 4 中可以看到一個示例傳輸函數(shù)。
圖 4 – 從緩沖區(qū)彈出數(shù)據(jù)在健壯的應(yīng)用程序中,還應(yīng)檢查循環(huán)緩沖區(qū)長度和溢出狀態(tài)。CBUF 模塊確實提供了能夠檢查這些重要指標的宏。
要記住的一個重要問題是,如果需要對 CBUF 本身進行任何調(diào)試,這是不可能的。無法為宏設(shè)置斷點,因此如果出現(xiàn)問題,則需要對模塊進行功能化以逐步執(zhí)行和調(diào)試。
多年來使用這個模塊雖然我沒有發(fā)現(xiàn)任何問題。循環(huán)緩沖區(qū)是在嵌入式系統(tǒng)中與串行設(shè)備通信的一個重要方面。
循環(huán)緩沖區(qū)也很好理解,應(yīng)該創(chuàng)建它們以便它們可以模塊化并從一個應(yīng)用程序到下一個應(yīng)用程序重復(fù)使用。
到目前為止,CBUF 模塊已被證明是這樣一個模塊,所以在這里,我強烈推薦一下這個模塊。好了,今天的文章就到這里,我們下期再見。
再貼上代碼的注釋部分
推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識小密圈
關(guān)注公眾號,后臺回復(fù)「1024」獲取學習資料網(wǎng)盤鏈接。
歡迎點贊,關(guān)注,轉(zhuǎn)發(fā),在看,您的每一次鼓勵,我都將銘記于心~
總結(jié)
以上是生活随笔為你收集整理的优雅地用宏实现环形缓冲区的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《算法第4版》与《算法导论》比较
- 下一篇: 程序员入门:三本必看的书