「星標公眾號」,一起進步!
來源:https://github.com/54zorb/Zorb-Framework
Zorb Framework是一個基于面向對象的思想來搭建一個輕量級的嵌入式框架。
本次分享的是Zorb Framework的環(huán)形緩沖區(qū)功能zf_buffer。
環(huán)形緩沖區(qū)主要應用在字節(jié)數(shù)據(jù)流傳輸上,如串口、網(wǎng)口的收發(fā)都可以通過環(huán)形緩沖區(qū)進行緩存。
例如我要通過串口發(fā)送命令“LED ON”來控制開發(fā)板的led燈亮起來,但開發(fā)板串口接收不是一次把“LED ON”同時接收,而是一個字節(jié)一個字節(jié)地接收,因此需要使用緩沖區(qū)來緩存數(shù)據(jù),然后解析器來解析緩沖區(qū)的數(shù)據(jù)。
我們先來看看要實現(xiàn)的緩沖區(qū)長什么樣子,提供什么功能,這樣方便我們設計。
初步要提供的功能如下:
1、要有可以緩存數(shù)據(jù)的空間
2、可以知道總空間的大小
3、可以知道已用空間的數(shù)量
4、可以壓入數(shù)據(jù)
5、可以彈出數(shù)據(jù)
6、我也可以在不彈出數(shù)據(jù)的情況下,讀到特定長度的數(shù)據(jù)
因此,初步設計的數(shù)據(jù)結構如下:
/*?環(huán)形緩沖區(qū)數(shù)據(jù)結構?*/
typedef?struct?_RingBuffer
{
????bool?IsExternBuffer;??/*?是否外部緩沖區(qū),是則銷毀時不釋放?*/
????uint8_t?*pBuf;????????/*?緩沖區(qū)指針?*/
????uint32_t?Head;????????/*?緩沖區(qū)頭地址?*/
????uint32_t?Trail;???????/*?緩沖區(qū)尾地址?*/
????uint32_t?Size;????????/*?緩沖區(qū)大小?*/
????uint32_t?Count;???????/*?數(shù)據(jù)字節(jié)數(shù)?*/
????/*?緩沖器是否已滿?*/
????bool?(*IsFull)(struct?_RingBuffer?*?const?pRb);
????/*?緩沖器是否空?*/
????bool?(*IsEmpty)(struct?_RingBuffer?*?const?pRb);
????/*?壓入一個字節(jié)?*/
????bool?(*SaveByte)(struct?_RingBuffer?*?const?pRb,?uint8_t?byte);
????/*?取出一個字節(jié)?*/
????bool?(*GetByte)(struct?_RingBuffer?*?const?pRb,?uint8_t?*pByte);
????/*?讀取緩沖器已使用字節(jié)個數(shù)?*/
????uint32_t?(*GetCount)(struct?_RingBuffer?*?const?pRb);
????/*?讀取n個字節(jié)(n超過最大數(shù)據(jù)數(shù)時全部讀出)?*/
????bool?(*ReadBytes)(struct?_RingBuffer?*?const?pRb,?uint8_t?*pArray,
????????uint32_t?n);
????/*?丟棄n個字節(jié)(n超過最大數(shù)據(jù)數(shù)時全部丟棄)?*/
????bool?(*DropBytes)(struct?_RingBuffer?*?const?pRb,?uint32_t?n);
????/*?清空緩沖器?*/
????bool?(*Clear)(struct?_RingBuffer?*?const?pRb);
????/*?釋放緩沖器(不釋放外部創(chuàng)建的緩沖區(qū))?*/
????bool?(*Dispose)(struct?_RingBuffer?*?const?pRb);
}?RingBuffer;
其實按實際需要,可能遠不止上面提到的6種情況,例如我可以丟棄特定數(shù)量的字節(jié)數(shù)據(jù),也可以直接清空掉緩沖區(qū)數(shù)據(jù),甚至可以設想提供動態(tài)緩沖區(qū)的功能,也就是說可以釋放緩沖器自己。
/******************************************************************************
?*?描述??:創(chuàng)建環(huán)形緩沖器(內(nèi)部分配空間,size=0表示使用外部數(shù)據(jù))
?*?參數(shù)??:(out)-ppRb ?環(huán)形緩沖器結構體指針的指針
?*?????????(in)-size???緩沖器大小
?*?????????(out)-ppBuf?緩沖器空間指針的指針
?*?返回??:無
******************************************************************************/
bool?RB_create(RingBuffer?**ppRb,?uint32_t?size)
{
????RingBuffer?*pRb;
????uint8_t?*pBuf;
????
????ZF_ASSERT(ppRb?!=?(RingBuffer?**)0)
????
????pRb?=?(RingBuffer?*)ZF_MALLOC(sizeof(RingBuffer));
????if?(pRb?==?NULL)
????{
????????ZF_DEBUG(LOG_E,?"malloc?ringbuffer?space?error\r\n");
????????return?false;
????}
????
????pRb->Head?=?(uint32_t)0;
????pRb->Trail?=?(uint32_t)0;
????pRb->Count?=?0;
????
????if?(size?>?0)
????{
????????pBuf?=?(void?*)ZF_MALLOC(size);
????????if?(pBuf?==?NULL)
????????{
????????????ZF_DEBUG(LOG_E,?"malloc?ringbuffer?buffer?space?error\r\n");
????????????return?false;
????????}
????????
????????pRb->pBuf?=?pBuf;
????????pRb->Size?=?size;
????????pRb->IsExternBuffer?=?false;
????}
????else
????{
????????pRb->pBuf?=?NULL;
????????pRb->Size?=?0;
????????pRb->IsExternBuffer?=?true;
????}
????
????/*?初始化方法?*/
????pRb->IsFull?=?RB_isFull;
????pRb->IsEmpty?=?RB_isEmpty;
????pRb->SaveByte?=?RB_saveByte;
????pRb->SaveRange?=?RB_saveRange;
????pRb->GetByte?=?RB_getByte;
????pRb->GetCount?=?RB_getCount;
????pRb->ReadBytes?=?RB_readBytes;
????pRb->DropBytes?=?RB_dropBytes;
????pRb->Clear?=?RB_clear;
????pRb->Dispose?=?RB_dispose;
????
????/*?輸出?*/
????*ppRb?=?pRb;
????
????return?true;
}
/******************************************************************************
?*?描述??:釋放緩沖器(不釋放外部創(chuàng)建的緩沖區(qū))
?*?參數(shù)??:(in)-pRb ????環(huán)形緩沖器結構體指針
?*?返回??:-true ????成功
?*?????????-false????失敗
******************************************************************************/
bool?RB_dispose(RingBuffer?*?const?pRb)
{
????ZF_ASSERT(pRb?!=?(RingBuffer?*)0)
????
????/*?外部創(chuàng)建的緩沖區(qū)不釋放?*/
????if?(!pRb->IsExternBuffer)
????{
????????ZF_FREE(pRb->pBuf);
????}
????
????ZF_FREE(pRb);
????
????return?true;
}
/******************************************************************************
?*?描述??:壓入一個字節(jié)
?*?參數(shù)??:(in)-pRb ?環(huán)形緩沖器結構體指針
?*?????????(in)-byte?要壓入的字節(jié)
?*?返回??:-true ????成功
?*?????????-false????失敗
******************************************************************************/
bool?RB_saveByte(RingBuffer?*?const?pRb,?uint8_t?byte)
{
????bool?res?=?false;
????
????ZF_ASSERT(pRb?!=?(RingBuffer?*)0)
????ZF_ASSERT(pRb->pBuf?!=?(uint8_t?*)0)
????
????if?(!RB_isFull(pRb))
????{
????????pRb->pBuf[pRb->Trail++]?=?byte;
????????pRb->Trail?%=?pRb->Size;
????????pRb->Count++;
????????
????????res?=?true;
????}
????
????return?res;
}
/******************************************************************************
?*?描述??:取出一個字節(jié)
?*?參數(shù)??:(in)-pRb ???環(huán)形緩沖器結構體指針
?*?????????(out)-pByte?存放取出字節(jié)的地址
?*?返回??:-true ??????成功
?*?????????-false??????失敗
******************************************************************************/
bool?RB_getByte(RingBuffer?*?const?pRb,?uint8_t?*pByte)
{
????bool?res?=?false;
????
????ZF_ASSERT(pRb?!=?(RingBuffer?*)0)
????ZF_ASSERT(pRb->pBuf?!=?(uint8_t?*)0)
????ZF_ASSERT(pByte?!=?(uint8_t?*)0)
????
????if?(!RB_isEmpty(pRb))
????{
????????*pByte?=?pRb->pBuf[pRb->Head++];
????????pRb->Head?%=?pRb->Size;
????????pRb->Count--;
????????
????????res?=?true;
????}
????
????return?res;
}
/**
??*****************************************************************************
??*?@file????app_buffer.c
??*?@author??Zorb
??*?@version?V1.0.0
??*?@date????2018-06-28
??*?@brief???環(huán)形緩沖區(qū)測試的實現(xiàn)
??*****************************************************************************
??*?@history
??*
??*?1.?Date:2018-06-28
??*????Author:Zorb
??*????Modification:建立文件
??*
??*****************************************************************************
??*/
#include?"app_buffer.h"
#include?"zf_includes.h"
/*?環(huán)形緩沖區(qū)指針?*/
RingBuffer?*rb;
/******************************************************************************
?*?描述??:任務初始化
?*?參數(shù)??:無
?*?返回??:無
******************************************************************************/
void?App_Buffer_init(void)
{
????/*?創(chuàng)建500字節(jié)的緩沖區(qū)?*/
????RB_create(&rb,?500);
}
/******************************************************************************
?*?描述??:任務程序
?*?參數(shù)??:無
?*?返回??:無
******************************************************************************/
void?App_Buffer_process(void)
{
????uint32_t?i;
????uint8_t?buf[11];
????uint8_t?byte;
????ZF_DEBUG(LOG_D,?"rb?count?before?adding?data?is?%d\r\n",?rb->Count);
????/*?填充10個字節(jié)數(shù)據(jù)(0-9)?*/
????for?(i?=?0;?i?10;?i++)
????{
????????rb->SaveByte(rb,?i);
????}
????ZF_DEBUG(LOG_D,?"rb?count?after?adding?data?is?%d\r\n",?rb->Count);
????/*?讀出數(shù)據(jù)看是否正確?*/
????rb->ReadBytes(rb,?buf,?10);
????ZF_DEBUG(LOG_D,?"rb?data?is?");
????for?(i?=?0;?i?10;?i++)
????{
????????ZF_DEBUG(LOG_D,?"%d?",?buf[i]);
????}
????ZF_DEBUG(LOG_D,?"\r\n\r\n");
????/*?彈出數(shù)據(jù)?*/
????for?(i?=?0;?i?10;?i++)
????{
????????rb->GetByte(rb,?&byte);
????????ZF_DEBUG(LOG_D,?"byte?%d?is?%d\r\n",?i,?byte);
????????ZF_DEBUG(LOG_D,?"rb?count?is?%d\r\n",?rb->Count);
????}
????while(1);
}
/********************************?END?OF?FILE?********************************/
結果:

本文來源網(wǎng)絡,免費傳達知識,版權歸原作者所有。如涉及作品版權問題,請聯(lián)系我進行刪除。
《嵌入式Linux驅動大全》
如何高效閱讀嵌入式項目代碼?