0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式開發(fā)模塊指南:通用接收狀態(tài)機(jī)模塊

技術(shù)讓夢(mèng)想更偉大 ? 來源:CSDN-夏日白云 ? 2023-03-28 09:28 ? 次閱讀

前言

在軟件開發(fā)的過程中,只要涉及到通信,就會(huì)涉及到數(shù)據(jù)接收機(jī)的編寫,通信協(xié)議雖然多種多樣,但是數(shù)據(jù)包的形式確是很相似的(暫時(shí)沒看到特別復(fù)雜,此模塊解決不了的),為此可以把其中通用的部分抽象出來,然后就成了這個(gè)模塊。

模塊相關(guān)概念和邏輯

接收機(jī)狀態(tài)

接收機(jī)有兩個(gè)基本狀態(tài):

狀態(tài)A:preRx 等待幀頭中,這個(gè)時(shí)候接收機(jī)會(huì)不斷判斷是否收到了特殊序列、幀頭和強(qiáng)幀尾。如果收到了幀頭,則(默認(rèn))會(huì)把幀頭填入緩沖區(qū)的最前面,然后進(jìn)入狀態(tài)B。

狀態(tài)B:Rxing 等待幀尾中,收到的數(shù)據(jù)會(huì)按序填入接收緩沖區(qū),同時(shí)不斷查找?guī)?、?qiáng)幀頭以及強(qiáng)特殊序列,不管找到了哪一個(gè)都會(huì)觸發(fā)flush。如果,找到的是強(qiáng)幀頭,則仍然在狀態(tài)B,否則恢復(fù)狀態(tài)A。

不管在哪一個(gè)狀態(tài)下,如果接受緩沖區(qū)滿了,都會(huì)觸發(fā)flush并回到狀態(tài)A。

標(biāo)志字符序列

接收機(jī)定義了以下標(biāo)志序列類型:

類型 模塊中標(biāo)記 描述
幀頭 header 只在狀態(tài)A起作用;找到時(shí)會(huì)導(dǎo)致之前接收區(qū)內(nèi)的數(shù)據(jù)被flush,然后默認(rèn)會(huì)填入接收區(qū)的最前面,可以通過選項(xiàng)來改變這個(gè)行為,然后接收機(jī)進(jìn)入狀態(tài)B。
強(qiáng)幀頭 strong-header 在狀態(tài)B也會(huì)起作用,其他行為與普通幀頭一樣
幀尾 ender 只在狀態(tài)B起作用;找到時(shí)會(huì)導(dǎo)致當(dāng)前接收區(qū)內(nèi)的數(shù)據(jù)被flush,默認(rèn)會(huì)處于回調(diào)時(shí)給用戶的buffer的最后面,可以通過選項(xiàng)來改變這個(gè)行為,然后接收機(jī)回到狀態(tài)A。
強(qiáng)幀頭 strong-header 在狀態(tài)A也會(huì)起作用,其他行為與普通幀尾一樣
特殊序列 unique 只在狀態(tài)A起作用;找到時(shí)會(huì)導(dǎo)致之前接收區(qū)內(nèi)的數(shù)據(jù)被flush,然后自己被填入接收區(qū)內(nèi)后再次觸發(fā)flush,然后接收機(jī)回到狀態(tài)A。
強(qiáng)特殊序列 strong-unique 在狀態(tài)B也會(huì)起作用,其他行為與特殊序列一樣

對(duì)應(yīng)模塊中的結(jié)構(gòu)體為:

//receiveflag
typedefstructRXFLAG_STRUCT{
uint8_tconst*pBuf;
uint8_tlen;
uint8_toption;
}RXFLAG_STRUCT;
typedefRXFLAG_STRUCTconst*RxFlag;
1234567

一般的流程中,初始化接收機(jī)前,用戶需要準(zhǔn)備好接收機(jī)使用的所有標(biāo)志序列,標(biāo)志好每個(gè)序列的類型。模塊提供宏函數(shù)以抽象這個(gè)過程:

//voidRxFlag_Init(RXFLAG_STRUCT*flag,uint8_tconst*buf,uint8_tlen,uint8_topt);
//toinitializeareceiveflag
//flagpointtothetargetRXFLAG_STRUCT.
//bufpointertotheflagbuffer
//sizesizeofflag
//optseeRXFLAG_OPTION_XXXXX,bitmode
#defineRxFlag_Init(flag,buf,size,opt)
{(flag)->pBuf=(buf);(flag)->len=(size);(flag)->option=(opt);}

flush

每當(dāng)接收機(jī)根據(jù)標(biāo)志字符序列找到一個(gè)完整或不完整的數(shù)據(jù)包時(shí),接收機(jī)會(huì)進(jìn)行回調(diào)以通知用戶處理這個(gè)數(shù)據(jù)包,這個(gè)行為被稱為flush,這個(gè)回調(diào)函數(shù)叫做onFlushed。

此函數(shù)的原型如下

typedefvoid(*RXMAC_FLUSH_EVENT)(RxMacsender,RxMacPtrbuf,uint16_tlen,RxStatestate,
RxFlagHorU,RxFlagEnder);

整個(gè)數(shù)據(jù)包為buf指向的長度為len的區(qū)域。

數(shù)據(jù)包的狀態(tài)可以通過state參數(shù)得知,RX_STATE 的類型定義如下

typedefstructRXSTATE_STRUCT{
unsignedintheaderFound:1;//1:havegetheader
unsignedintenderFound:1;//1:havegetender
unsignedintisFull:1;//1:thebufferisfull
unsignedintuniqueFound:1;//1:thisisuniqueflag.
}RxState;

通過判斷每個(gè)標(biāo)志位是否置1,可以得知當(dāng)前數(shù)據(jù)包的狀態(tài)。
如果headerFound == 1,說明數(shù)據(jù)包是有幀頭的,可以通過pHorU獲得幀頭
如果enderFound == 1,說明數(shù)據(jù)包是有幀尾的,可以通過pEnder獲得幀尾
如果isFull == 1,說明此數(shù)據(jù)包是因?yàn)榻邮諈^(qū)滿了放不下了而產(chǎn)生的回調(diào),在一些需要根據(jù)某個(gè)字段來判斷數(shù)據(jù)包真正大小的協(xié)議里,可以通過調(diào)整接收緩沖區(qū)的大小來恰當(dāng)?shù)漠a(chǎn)生flush。
如果UniqueFound == 1,說明此數(shù)據(jù)包是標(biāo)志序列,這時(shí)緩沖區(qū)內(nèi)的內(nèi)容等于pHorU指向的那個(gè)標(biāo)志序列

接收機(jī)類

V1.0版本中要求用戶自己分配結(jié)構(gòu)體的空間,為了更加面向?qū)ο?,現(xiàn)已改為動(dòng)態(tài)分配,而把具體結(jié)構(gòu)體和對(duì)應(yīng)方法封裝在模塊內(nèi)部。

typedefstructRXMAC_STRUCT*RxMac;

模塊提供Create函數(shù)來創(chuàng)建接收機(jī)實(shí)例并返回指向?qū)嵗闹羔槨?/p>

//tocreateaninstanceofRxMac
//flags標(biāo)志字符串結(jié)構(gòu)體的數(shù)組
//flagsCnt標(biāo)志字符串結(jié)構(gòu)體的個(gè)數(shù)
//buf用戶提供給接收機(jī)用的緩沖區(qū)
//bufLen緩沖區(qū)的大小(起碼應(yīng)該要能放的下最長的標(biāo)志字符串)
//onFeeded在每次被Feed時(shí)觸發(fā)
//onGetHeader獲得頭標(biāo)志位時(shí)觸發(fā)。
//onFlushed收到一幀數(shù)據(jù)時(shí)的回調(diào)函數(shù)
RxMacRxMac_Create(RXFLAG_STRUCTconstflags[],uint8_tflagsCnt,RxMacPtrbuf,uint16_tbufLen,
RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed);

調(diào)用實(shí)例的方法時(shí)把這個(gè)指針作為第一個(gè)參數(shù)以模擬面向?qū)ο蟛僮鳌?/p>

過濾器

接收機(jī)每次被feed時(shí),都會(huì)觸發(fā)onFeeded事件(可以在配置中取消這個(gè)事件以節(jié)省點(diǎn)代碼)。原型如下:

typedefvoid(*RXMAC_FILTER)(RxMacsender,uint8_t*pCurChar,uint16_tbytesCnt);

pCurChar :指向接收區(qū)中剛收到的字符
bytesCnt :這個(gè)字符是接收區(qū)中的第幾個(gè)字符

此時(shí),接收機(jī)已經(jīng)將其放入接收區(qū)但是還沒進(jìn)一步進(jìn)行判斷,用戶可以修改字符/配置接收機(jī)以改變接收機(jī)的行為,比如將收到的字母全變?yōu)樾??;蛘吒鶕?jù)收到的數(shù)據(jù)來決定還要收多少數(shù)據(jù)。

onGetHeader事件

當(dāng)找到任意幀頭時(shí)會(huì)觸發(fā)。

接收機(jī)運(yùn)行邏輯

接收機(jī)的運(yùn)作邏輯如下:

6fb489b2-ccde-11ed-bfe3-dac502259ad0.pngimg

邊際條件

標(biāo)志序列盡量不要有重合,如果同時(shí)可能匹配兩個(gè)標(biāo)志序列,最終行為是未定義的,不保證正確執(zhí)行,最終結(jié)果可能與標(biāo)志序列的位置以及類型有關(guān)系。

同一個(gè)標(biāo)志串可以同時(shí)是多種類型,比如同時(shí)是幀頭與幀尾,但要小心類型間不要有沖突,否則不保證正確執(zhí)行。

對(duì)于標(biāo)志序列匹配到一半發(fā)生了接收緩沖區(qū)滿,從而導(dǎo)致發(fā)生標(biāo)志序列匹配時(shí),接收緩沖區(qū)中只有半個(gè)標(biāo)志序列的情況:
如果標(biāo)志序列是(強(qiáng))特殊序列或(強(qiáng))幀頭的情況,可以保證功能正常運(yùn)行。
如果標(biāo)志序列是強(qiáng)幀尾的情況,緩沖區(qū)內(nèi)會(huì)只剩下后半段的幀尾,但可以根據(jù)pEnder參數(shù)來得知真正的幀尾。
幀尾不會(huì)發(fā)生這種邊際條件。

相關(guān)代碼

此模塊使用了我自己寫的Buffer模塊作為內(nèi)部緩沖區(qū)來判斷標(biāo)志字符串。
[嵌入式開發(fā)模塊]環(huán)形緩沖區(qū)/循環(huán)隊(duì)列 C語言實(shí)現(xiàn)

接收機(jī)代碼

RxMac.h

/*
*******************************************************************************************
*
*
*UniversalReceiveStateMachine
*通用接收狀態(tài)機(jī)
*
*File:RxMac.h
*By:LinShijun(https://blog.csdn.net/lin_strong)
*Date:2019/03/07
*version:2.1
*History:2018/05/291.0theprototype
*2019/01/232.0modifythetypenamestomorereadableones,thoughpreserve
*theold-styleforforwardcompatibility;
*changeinitmethodtocreatemethodwhichusemalloctoalloc
*instance,andthecorrespondingdestroymethod.
*changetheinternalbuffermodulefromRINGQUEUEtoBufferArray,
*sousernolongerneedtoknowtheinternalflagsmanagementand
*allocatethespaceforit.
*addRxMac_FeedDatasmethodforconvenient.
*2019/03/072.1somemodificationtothemallocconfiguration
*
*NOTE(s):1.thereceiveprocesshastwobasicstate
*A.preRx:whenhaven'tfoundanyheader,theRxMacwillsearchfortheunique
*flag,headerandstrong-ender.Onlywhenaheaderisfoundwillcome
*tonextstep.
*B.Rxing:theRxMacwillputthesuccessivebytesintothebuffer,andsearch
*forthestrong-unique,strong-header,ender.
*2.themoduleisdrivedbytheRxMac_FeedData(),usershouldgetthethechar
*fromdatastreamandpassthedataonebyonetotheRxMacthroughRxMac_FeedData()
*orRxMac_FeedDatas().
*3.eachtimeRxMacfindaframe(completeorincomplete),itwillcalltheonFlushed
*tonotifytheresults;usercanjudgetheframethroughthestateparameter;
*state.headerFound==1:findanyheader,theheaderispassedbyHorU
*state.enderFound==1:findanyender,theenderispassedbyEnder
*state.isFull==1:thebufferisfull,maybeyoushouldcheckheaderFound
*toseewhetheraheaderhasbeenfound.
*state.uniqueFound==1:findanyuniqueflag.Inthiscase,otherparameterswill
*alwaysbe0,thedatainthebufferwillbetheflag,
*andtheuniqueflagispassedbyHorU.
*4.Tousethismodule,foreachreceivemachine:
*A.definemalloctoconfigurethemodule,seeCONFIGURATION
*B.allocatethespaceforbufferandFLAGS.
*RXFLAG_STRUCTflags[2];
*uint8_tbuf[300];
*C.settheflagsaccordingtotheprotocol,definethecallbackfunctions
*accordingtoyourneed.
*staticvoidonGetHeader(RxMacsender,RxFlagpFlag){......};
*staticvoidonFlushed(RxMacsender,RxMacPtrpBuf,uint16_tlen,
*RxStatestate,RxFlagHorU,RxFlagEnder){......};
*constuint8_tHeaderFlag[]="Header";
*constuint8_tEnderFlag[]="
";
*RxFlag_Init(flags,HeaderFlag,StrSize(HeaderFlag),RXFLAG_OPTION_HEADER);
*RxFlag_Init(&flags[1],EnderFlag,StrSize(EnderFlag),RXFLAG_OPTION_ENDER|
*RXFLAG_OPTION_NOTFILL_ENDER);
*D.createthereceivemachine:
*RxMacmac;
*mac=RxMac_Create(flags,sizeof(flags)/sizeof(flags[0]),buf,300,NULL,
*onGetHeader,onFlushed);
*E.feedthereceivemachine:
*while(1){
*c=GetNextChar();
*RxMac_FeedData(mac,c);
*}
*F.destroythereceivemachineifneed.
*RxMac_Destroy(mac);
*******************************************************************************************
*/

#ifndefRX_MAC_H
#defineRX_MAC_H

/*
*******************************************************************************************
*INCLUDES
*******************************************************************************************
*/

#include

/*
*******************************************************************************************
*CONFIGURATION配置
*******************************************************************************************
*/
//#defineRXMAC_ARGUMENT_CHECK_DISABLEtodisabletheargumentcheckfunctionsofthismodule
//#defineRXMAC_ARGUMENT_CHECK_DISABLE

//#defineRXMAC_NOTFILL_DISABLEtodisablethenotFilloption
//#defineRXMAC_NOTFILL_DISABLE

//#defineRXMAC_ONFEEDED_DISABLEtodisabletheonFeededevent.
//#defineRXMAC_ONFEEDED_DISABLE

//#defineRXMAC_SINGLETON_ENtousesingletonpattern,soargumentpRxMacofinterfacesis
//useless,anduserdon'tneedtoallocatespaceforRX_MAC,butyoustillneedtoallocate
//bufferandcallinit();
//#defineRXMAC_SINGLETON_EN

//#defineRXMAC_BUF_RPAGEifyouwantreceivemachineusethepagedarrayasbuffer.
//anddon'tforgettodefineCODEWARRIORmalloc
//#defineRXMAC_BUF_RPAGE
/*
*******************************************************************************************
*ADDRESSINGMODE尋址模式
*******************************************************************************************
*/

#ifdefRXMAC_BUF_RPAGE
#ifdefCODEWARRIOR
#defineRXMAC_BUF_ADDRESSING_MODE__rptr
#endif
#endif

#ifndefRXMAC_BUF_ADDRESSING_MODE
#defineRXMAC_BUF_ADDRESSING_MODE
#endif
typedefuint8_t*RXMAC_BUF_ADDRESSING_MODERxMacPtr;

/*
*********************************************************************************************
*ERRORCODE
*********************************************************************************************
*/

#defineRXMAC_ERR_NONE0
#defineRXMAC_ERR_ARGUMENT1
#defineRXMAC_ERR_POINTERNULL2
#defineRXMAC_ERR_UNKNOWN3
#defineRXMAC_ERR_INIT4

/*
*********************************************************************************************
*RECEIVEFLAGSTRUCT
*********************************************************************************************
*/

//normalheader,RxMacwillonlycheckitinStepA
#defineRXFLAG_OPTION_HEADER0x01
//strongheader,RxMacwillalwayscheckit.
#defineRXFLAG_OPTION_STRONG_HEADER0x03
//theheaderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisheader)
#defineRXFLAG_OPTION_NOTFILL_HEADER0x04
//normalender,RxMacwillonlycheckitinStepB
#defineRXFLAG_OPTION_ENDER0x08
//strongheader,RxMacwillalwayscheckit.
#defineRXFLAG_OPTION_STRONG_ENDER0x18
//theenderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisender)
#defineRXFLAG_OPTION_NOTFILL_ENDER0x20
//normalunique,RxMacwillonlycheckitinStepA
#defineRXFLAG_OPTION_UNIQUE0x40
//strongunique,RxMacwillalwayscheckit.
#defineRXFLAG_OPTION_STRONG_UNIQUE0xC0

//receiveflag
typedefstructRXFLAG_STRUCT{
uint8_tconst*pBuf;
uint8_tlen;
uint8_toption;
}RXFLAG_STRUCT;
typedefRXFLAG_STRUCTconst*RxFlag;

//voidRxFlag_Init(RXFLAG_STRUCT*flag,uint8_tconst*buf,uint8_tlen,uint8_topt);
//toinitializeareceiveflag
//flagpointtothetargetRXFLAG_STRUCT.
//bufpointertotheflagbuffer
//sizesizeofflag
//optseeRXFLAG_OPTION_XXXXX,bitmode
#defineRxFlag_Init(flag,buf,size,opt)
{(flag)->pBuf=(buf);(flag)->len=(size);(flag)->option=(opt);}


/*
*********************************************************************************************
*TYPEDEFINITION
*********************************************************************************************
*/

typedefstructRXSTATE_STRUCT{
unsignedintheaderFound:1;//1:havegetheader
unsignedintenderFound:1;//1:havegetender
unsignedintisFull:1;//1:thebufferisfull
unsignedintuniqueFound:1;//1:thisisuniqueflag.
}RxState;

typedefstructRXMAC_STRUCT*RxMac;

typedefvoid(*RXMAC_FLUSH_EVENT)(RxMacsender,RxMacPtrbuf,uint16_tlen,RxStatestate,
RxFlagHorU,RxFlagEnder);
typedefvoid(*RXMAC_FLAG_EVENT)(RxMacsender,RxFlagflag);
typedefvoid(*RXMAC_FILTER)(RxMacsender,uint8_t*pCurChar,uint16_tbytesCnt);

/*
*******************************************************************************************
*FUNCTIONDECLARATION
*******************************************************************************************
*/

//tocreateaninstanceofRxMac
//flags標(biāo)志字符串結(jié)構(gòu)體的數(shù)組
//flagsCnt標(biāo)志字符串結(jié)構(gòu)體的個(gè)數(shù)
//buf用戶提供給接收機(jī)用的緩沖區(qū)
//bufLen緩沖區(qū)的大小(起碼應(yīng)該要能放的下最長的標(biāo)志字符串)
//onFeeded在每次被Feed時(shí)觸發(fā)
//onGetHeader獲得頭標(biāo)志位時(shí)觸發(fā)。
//onFlushed收到一幀數(shù)據(jù)時(shí)的回調(diào)函數(shù)
RxMacRxMac_Create(RXFLAG_STRUCTconstflags[],uint8_tflagsCnt,RxMacPtrbuf,uint16_tbufLen,RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed);
//todestroytheRxMac
voidRxMac_Destroy(RxMacmac);
//向接收機(jī)內(nèi)喂字節(jié)
voidRxMac_FeedDatas(RxMacmac,uint8_tconst*buf,uint16_tlen);
voidRxMac_FeedData(RxMacmac,uint8_tc);
//重置接收區(qū)長度為最長那個(gè)長度
//uint8_tRxMac_ResetRxSize(RxMacmac);
//設(shè)置最大接收到多少個(gè)字節(jié)
uint8_tRxMac_SetRxSize(RxMacmac,uint16_tsize);
//重置接收機(jī)的狀態(tài)
uint8_tRxMac_ResetState(RxMacmac);
//強(qiáng)制接收機(jī)flush
uint8_tRxMac_Flush(RxMacmac);
//設(shè)置onFeeded
uint8_tRxMac_SetOnFeeded(RxMacmac,RXMAC_FILTERonFeeded);
//設(shè)置onGetHeader
uint8_tRxMac_SetOnGetHeader(RxMacmac,RXMAC_FLAG_EVENTonGetHeader);
//設(shè)置onFlushed
uint8_tRxMac_SetOnFlushed(RxMacmac,RXMAC_FLUSH_EVENTonFlushed);

#include"RxMacPrivate.h"

#endif//ofRX_MAC_H

RxMacPrivate.h

/*
*******************************************************************************************
*
*
*PrivateDeclarationsforUniversalReceiveStateMachine
*
*File:RxMacPrivate.h
*By:LinShijun(https://blog.csdn.net/lin_strong)
*Date:2019/03/07
*version:2.1
*History:
*NOTE(s):
*******************************************************************************************
*/


/*
*******************************************************************************************
*FUNCTIONDECLARATION
*******************************************************************************************
*/
//打印內(nèi)部緩沖區(qū),返回緩沖區(qū)的長度
uint16_t_RxMac_printBuffer(RxMacmac,uint8_t*buf);

/*
*******************************************************************************************
*RECEIVEFLAGSTRUCT
*******************************************************************************************
*/

//structofRXFLAG_STRUCT.option
/*typedefstructRXFLAG_OPTION{
unsignedintisHeader:1;//1:theflagistheheadoftheframe
unsignedintstrong_H:1;//1:strong-header,RxMacwill
unsignedintnotfill_H:1;//0:filltheflagintothebufferwhenfoundasheader
unsignedintisEnder:1;//1:theflagistheendoftheframe
unsignedintstrong_E:1;//
unsignedintnotfill_E:1;//0:filltheflagintothebufferwhenfoundasender
unsignedintisUnique:1;//1:theflagisauniqueflagwhichistreatedassingleframe.
unsignedintstrong_U:1;//0:whenreceivingaframe,RxMacwillnot
};//*/
//normalheader,RxMacwillonlycheckitinStepA
#defineRXFLAG_OPTBIT_HEADER0x01
//strongheader,RxMacwillalwayscheckit.
#defineRXFLAG_OPTBIT_STRONG_HEADER0x02
//theheaderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisheader)
#defineRXFLAG_OPTBIT_NOTFILL_HEADER0x04
//normalender,RxMacwillonlycheckitinStepB
#defineRXFLAG_OPTBIT_ENDER0x08
//strongheader,RxMacwillalwayscheckit.
#defineRXFLAG_OPTBIT_STRONG_ENDER0x10
//theenderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisender)
#defineRXFLAG_OPTBIT_NOTFILL_ENDER0x20
//normalunique,RxMacwillonlycheckitinStepA
#defineRXFLAG_OPTBIT_UNIQUE0x40
//strongunique,RxMacwillalwayscheckit.
#defineRXFLAG_OPTBIT_STRONG_UNIQUE0x80

#defineSTATEMASK_STEPA
(RXFLAG_OPTBIT_HEADER|RXFLAG_OPTBIT_UNIQUE|RXFLAG_OPTBIT_STRONG_ENDER)
#defineSTATEMASK_STEPB
(RXFLAG_OPTBIT_STRONG_UNIQUE|RXFLAG_OPTBIT_ENDER|RXFLAG_OPTBIT_STRONG_HEADER)
#defineRXFLAGMASK_USUHSH
(RXFLAG_OPTBIT_HEADER|RXFLAG_OPTBIT_STRONG_HEADER|
RXFLAG_OPTBIT_UNIQUE|RXFLAG_OPTBIT_STRONG_UNIQUE)

//BOOL_RxFlag_isHeader(RxFlagflag);
#define_RxFlag_isHeader(flag)
((flag)->option&(RXFLAG_OPTION_STRONG_HEADER|RXFLAG_OPTION_HEADER))
//BOOL_RxFlag_isEnder(RxFlagflag);
#define_RxFlag_isEnder(flag)
((flag)->option&(RXFLAG_OPTION_STRONG_ENDER|RXFLAG_OPTION_ENDER))
//BOOL_RxFlag_isUnique(RxFlagflag);
#define_RxFlag_isUnique(flag)
((flag)->option&(RXFLAG_OPTION_STRONG_UNIQUE|RXFLAG_OPTION_UNIQUE))
//BOOL_RxFlag_dontFillHeader(RxFlagflag);
#define_RxFlag_dontFillHeader(flag)
((flag)->option&RXFLAG_OPTBIT_NOTFILL_HEADER)
//BOOL_RxFlag_dontFillEnder(RxFlagflag);
#define_RxFlag_dontFillEnder(flag)
((flag)->option&RXFLAG_OPTBIT_NOTFILL_ENDER)

/*
*******************************************************************************************
*FORWARDCOMPATIBILITY
*******************************************************************************************
*/
//以下僅為前向兼容
typedefRxMacPtrpRB_BYTE;
typedefRXFLAG_STRUCTRX_FLAG,*pRX_FLAG;
typedefRxMacpRX_MAC;
typedefRxStateRX_STATE;
#defineFLAG_OPTION_HEADERRXFLAG_OPTION_HEADER
#defineFLAG_OPTION_STRONG_HEADERRXFLAG_OPTION_STRONG_HEADER
#defineFLAG_OPTION_NOTFILL_HEADERRXFLAG_OPTION_NOTFILL_HEADER
#defineFLAG_OPTION_ENDERRXFLAG_OPTION_ENDER
#defineFLAG_OPTION_STRONG_ENDERRXFLAG_OPTION_STRONG_ENDER
#defineFLAG_OPTION_NOTFILL_ENDERRXFLAG_OPTION_NOTFILL_ENDER
#defineFLAG_OPTION_UNIQUERXFLAG_OPTION_UNIQUE
#defineFLAG_OPTION_STRONG_UNIQUERXFLAG_OPTION_STRONG_UNIQUE
#defineRX_FLAG_INITRxFlag_Init

RxMac.c

/*
*******************************************************************************************
*
*
*ImplementationoftheUniversalReceiveStateMachine
*通用接收狀態(tài)機(jī)
*
*File:RxMac.c
*By:LinShijun(https://blog.csdn.net/lin_strong)
*Date:2019/03/07
*version:2.1
*History:2018/05/291.0theprototype
*2019/01/232.0InadditiontothecontentinRxMac.h:
*abstracttheflagmanagementpartasRxFlagMgrandthe
*correspondingmethods.
*refactorthecode.
*2019/03/072.1somemodificationtothemallocconfiguration
*NOTE(s):
*
*******************************************************************************************
*/

/*
*******************************************************************************************
*INCLUDES
*******************************************************************************************
*/
#include
#include
#include
#include"RxMac.h"
#include"BufferMallocArray.h"

/*
*******************************************************************************************
*RECEIVEFLAGSMANAGER
*******************************************************************************************
*/

typedefstructRXFLAGMGR_STRUCT{
//buffertoholdthepre-datawhichhasn'tmatchedanyflag.
BufferUINT8IndexedBufForFlag;
//theflagarraytobematched.
RxFlagFlags;
//countofflags.
uint8_tFlagsCnt;
//currentstate,inwhichheaderFoundwillinfluencethematchbehavior.
//controlledbythechildclass.
RxStatestate;
}RXFLAGMGR_STRUCT;

staticRxFlag_RxFlagMgr_GetNextMatchedAtThisState(RxMacmac,uint8_tnextByte);
staticBOOL_RxFlagMgr_Init(RxMacmac,RxFlagflags,uint8_tflagsCnt,uint8_tmaxLen);
staticvoid_RxFlagMgr_Destroy(RxMacmac);
staticvoid_RxFlagMgr_Reset(RxMacmac);

/*
*******************************************************************************************
*STRUCTDIFINITION
*******************************************************************************************
*/

typedefstructRXMAC_STRUCT{
//managetheflagmatches.
RXFLAGMGR_STRUCTFlagMgr;
//recordtheHeaderorUniqueflag.
RxFlagpHorU;
//internalbuffertoholddata.
RxMacPtrpRxBuf;
//lengthoftheinternalbuffer
uint16_tRxBufSize;
//Countofthebytesintheinternalbuffer/theindexfornextfeededbyte
uint16_tRxCnt;
RXMAC_FILTERonFeeded;
RXMAC_FLAG_EVENTonGetHeader;
RXMAC_FLUSH_EVENTonFlushed;
}RXMAC_STRUCT;

/*
*******************************************************************************************
*LOCALFUNCITONDECLARATION
*******************************************************************************************
*/
#ifndefRXMAC_SINGLETON_EN
#define_pMacmac
#define_BufForFlag(_pMac->FlagMgr.BufForFlag)
#define_Flags(_pMac->FlagMgr.Flags)
#define_FlagsCnt(_pMac->FlagMgr.FlagsCnt)
#define_state(_pMac->FlagMgr.state)
#define_pHorU(_pMac->pHorU)
#define_pRxBuf(_pMac->pRxBuf)
#define_RxBufSize(_pMac->RxBufSize)
#define_RxCnt(_pMac->RxCnt)
#define_fonFeeded(_pMac->onFeeded)
#define_fonGetHeader(_pMac->onGetHeader)
#define_fonFlushed(_pMac->onFlushed)
#define_RxMac_Destroy()(free(mac))
#else
staticRXMAC_STRUCT_mac;
//單例模式中,這個(gè)指針用于標(biāo)識(shí)是否單例已初始化過
staticRxMac_pMac=NULL;
#define_BufForFlag(_mac.FlagMgr.BufForFlag)
#define_Flags(_mac.FlagMgr.Flags)
#define_FlagsCnt(_mac.FlagMgr.FlagsCnt)
#define_state(_mac.FlagMgr.state)
#define_pHorU(_mac.pHorU)
#define_pRxBuf(_mac.pRxBuf)
#define_RxBufSize(_mac.RxBufSize)
#define_RxCnt(_mac.RxCnt)
#define_fonFeeded(_mac.onFeeded)
#define_fonGetHeader(_mac.onGetHeader)
#define_fonFlushed(_mac.onFlushed)
#define_RxMac_Destroy()(_pMac=NULL)
#endif

#define_stateByte(*(uint8_t*)(&_state))
#define_isRxBufFull()(_RxCnt>=_RxBufSize)

#ifndefRXMAC_ONFEEDED_DISABLE
#define_onFeeded(pChar,cnt)if(_fonFeeded!=NULL)_fonFeeded(_pMac,pChar,cnt);
#else
#define_onFeeded(pChar,cnt)
#endif
#define_onGetHeader(headerFlag)if(_fonGetHeader!=NULL)_fonGetHeader(_pMac,headerFlag);

#undef_DONT_CHECK_MAC
#ifdefRXMAC_ARGUMENT_CHECK_DISABLE
#define_DONT_CHECK_MAC
#endif
#ifdefRXMAC_SINGLETON_EN
#define_DONT_CHECK_MAC
#endif

#ifdef_DONT_CHECK_MAC
#define_checkMacNotNull()
#define_checkMacNotNull_void()
#else
#define_checkMacNotNull()if(_pMac==NULL)returnRXMAC_ERR_POINTERNULL;
#define_checkMacNotNull_void()if(_pMac==NULL)return;
#endif


#ifdefRXMAC_BUF_RPAGE
#ifdefCODEWARRIOR
staticRxMacPtr_memcpy_internal(RxMacPtrdest,RxMacPtrsrc,size_tn);
#definememcpy(dest,src,n)_memcpy_internal(dest,src,n)
#endif
#endif
//沖刷緩沖區(qū)
staticvoid_flush(RxMacmac,RxFlagender);
//往接收機(jī)緩沖區(qū)內(nèi)放數(shù)據(jù)
staticvoid_BufIn(RxMacmac,RxMacPtrbuf,uint16_tlen);

staticvoid_RxMac_FlushIfFull(RxMacmac);
staticvoid_RxMac_RecordAndFlushPreBytesIfGotHeaderOrUnique(RxMacmac,RxFlagflagJustGot);
staticvoid_RxMac_GetHeaderProcess(RxMacmac,RxFlagflagJustGot);
staticvoid_RxMac_GetUniqueProcess(RxMacmac,RxFlagflagJustGot);
staticvoid_RxMac_GetEnderProcess(RxMacmac,RxFlagflagJustGot);
/*
*******************************************************************************************
*RxMac_Create()
*
*Description:Tocreateareceivemachineinstance.創(chuàng)建一個(gè)接收機(jī)實(shí)例
*
*Arguments:flagspointertotheflags(anarray);指向標(biāo)志串(數(shù)組)的指針
*flagsCntthecountoftheflags;有多少個(gè)標(biāo)志串;
*bufpointertothebufferprovidedtotheRxMac;提供給接收機(jī)使用的緩存
*bufLenthesizeofthebuffer.緩存的大小
*onFeededthecallbackfuncthatwillbecalledeverytimefeeded,you
*canmodifythefeededbyteinthiscallback.
*每次被feed時(shí)會(huì)調(diào)用的回調(diào)函數(shù),如改變對(duì)應(yīng)數(shù)據(jù)值會(huì)影響標(biāo)志位的判斷
*onGetHeaderthecallbackfuncthatwillbecalledwhenfindaheader.
*當(dāng)發(fā)現(xiàn)幀頭時(shí)會(huì)調(diào)用的回調(diào)函數(shù)
*onFlushedthecallbackfuncthatwillbecalledwhenflushed.
*當(dāng)Flush時(shí)會(huì)調(diào)用的回調(diào)函數(shù)
*
*Return:Pointertothecreatedinstance.
*NULLifanyerror.
*
*Note(s):1.sizeofbuffershouldbiggerthanthelongestflag,ortheflagwillbe
*useless.
*2.ifflagsCnt>0,flagscan'tpointtoNULL.
*3.youmustprovideabuffer.
*4.ifyouenabletheRXMAC_SINGLETON_EN,multi-createwillpointertothe
*sameinstanceinitializedasthelastcreate.
*
*voidonGetHeader(RxMacsender,RxFlagflag):
*senderthepointertotheRxMacwhichcallthisfunction
*flagtheheadermatched
*
*voidonFeeded(RxMacsender,uint8_t*pCurChar,uint16_tbytesCnt):
*senderthepointertotheRxMacwhichcallthisfunction
*pCurCharpointtothebytejustreceived,youcanchangeitbeforeanyotherprocess.
*bytesCntthenumberofbytesinthebufferincludingthecharjustfeeded.
*
*voidonFlushed(RxMacsender,RxMacPtrpBuf,uint16_tlen,RxStatestate,RxFlagHorU,
*RxFlagEnder);
*senderthepointertotheRxMacwhichcallthisfunction
*bufthepointertotheframe.
*lenthelengthofframe.
*statethestateofframe.
*HorUpointtotheheaderflagifstate.headerFound==1,oruniqueflagif
*state.uniqueFound==1.
*Enderpointtotheenderflagifstate.enderFound==1.
*******************************************************************************************
*/
RxMacRxMac_Create(RXFLAG_STRUCTconstflags[],uint8_tflagsCnt,RxMacPtrbuf,uint16_tbufLen,RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed){
uint8_ti,maxLen=0;
#ifndefRXMAC_SINGLETON_EN
RxMacmac;
#endif
#ifndefRXMAC_ARGUMENT_CHECK_DISABLE
if((flags==NULL&&flagsCnt>0)||buf==NULL)
returnNULL;
#endif
//findoutthemaxlengthofflags.
for(i=0;imaxLen)
maxLen=flags[i].len;
}
#ifndefRXMAC_ARGUMENT_CHECK_DISABLE
if(bufLen0)
*p++=*src++;
returndest;
}

staticvoid_BufIn(RxMacmac,RxMacPtrbuf,uint16_tlen){
memcpy(_pRxBuf+_RxCnt,buf,len);
_RxCnt+=len;
}

staticvoid_flush(RxMacmac,RxFlagender){
//觸發(fā)回調(diào)
if((_RxCnt>0||ender!=NULL)&&_fonFlushed!=NULL)
_fonFlushed(_pMac,_pRxBuf,_RxCnt,_state,_pHorU,ender);
//復(fù)位接收機(jī)
_RxCnt=0;
_stateByte=0;
_pHorU=NULL;
}

BOOLBufferUINT8Indexed_BackMatch(BufferUINT8Indexedbuf,uint8_tconst*toMatch,uint16_tlen){
uint16_tcnt=_Buffer_getCount(buf);
if(len>cnt)
returnFALSE;
while(len>0){
if(_BufferUINT8Indexed_get(buf,--cnt)!=toMatch[--len])
returnFALSE;
}
returnTRUE;
}


staticvoid_RxMac_FlushIfFull(RxMacmac){
if(_isRxBufFull()){
_state.isFull=1;
_flush(_pMac,NULL);
}
}

staticvoid_RxMac_RecordAndFlushPreBytesIfGotHeaderOrUnique(RxMacmac,RxFlagflagJustGot){
if(flagJustGot->option&RXFLAGMASK_USUHSH){
if(_RxCnt>flagJustGot->len){
_RxCnt-=flagJustGot->len;
_flush(_pMac,NULL);
}else{
_RxCnt=0;
}
_pHorU=flagJustGot;
}
}

staticvoid_RxMac_GetHeaderProcess(RxMacmac,RxFlagflagJustGot){
#ifndefRXMAC_NOTFILL_DISABLE
if(!_RxFlag_dontFillHeader(flagJustGot))
#endif
_BufIn(_pMac,(RxMacPtr)flagJustGot->pBuf,flagJustGot->len);
_state.headerFound=1;
_onGetHeader(flagJustGot);
_RxMac_FlushIfFull(mac);
}

staticvoid_RxMac_GetUniqueProcess(RxMacmac,RxFlagflagJustGot){
_state.uniqueFound=1;
_BufIn(_pMac,(RxMacPtr)flagJustGot->pBuf,flagJustGot->len);
_flush(_pMac,NULL);
}

staticvoid_RxMac_GetEnderProcess(RxMacmac,RxFlagflagJustGot){
_state.enderFound=1;
if(_RxCntlen){//ifpartoftheflaghasbeenmanuallyflushed.
_RxCnt=0;//restorethebuffer.
_BufIn(_pMac,(RxMacPtr)flagJustGot->pBuf,flagJustGot->len);
}
#ifndefRXMAC_NOTFILL_DISABLE
if(_RxFlag_dontFillEnder(flagJustGot))
if(_RxCnt>flagJustGot->len)
_RxCnt-=flagJustGot->len;
else
_RxCnt=0;
#endif
_flush(_pMac,flagJustGot);
}

staticRxFlag_RxFlagMgr_GetNextMatchedAtThisState(RxMacmac,uint8_tnextByte){
uint8_ti,mask;
if(_Buffer_isFull(_BufForFlag))
BufferUINT8_FrontOut((BufferUINT8)_BufForFlag);
BufferUINT8_BackIn((BufferUINT8)_BufForFlag,nextByte);
//masktoidentifypossibleflag
mask=(_state.headerFound)?STATEMASK_STEPB:STATEMASK_STEPA;
for(i=0;i

測(cè)試/示例代碼

已略去非必要代碼

#include
#include"RxMac.h"

/*
*********************************************************************************************************
*LOCALFUNCTIONDECLARE
*********************************************************************************************************
*/

staticvoidonGetData(RxMacsender,uint8_t*pCurChar,uint16_tbytesCnt);
staticvoidonFlushed(RxMacsender,RxMacPtrbuf,uint16_tlen,RxStatestate,RxFlagHorU,RxFlagEnder);
staticvoidonGetHeader(RxMacsender,RxFlagflag);
staticvoidonGetHeader2(RxMacsender,RxFlagflag);

/*
*********************************************************************************************************
*LOVALVARIABLE
*********************************************************************************************************
*/
staticRxMacmac=NULL;
staticRXFLAG_STRUCTflags[4];
#defineBUF_SIZE20
staticuint8_tbuffer[BUF_SIZE];

//協(xié)議示例1:
//幀頭:HEADER或者START
//強(qiáng)幀尾:END
//強(qiáng)特殊串:12345
//
staticvoidprotocol1_init(void){
RX_FLAG_INIT(&flags[0],"HEADER",6,FLAG_OPTION_HEADER);
RX_FLAG_INIT(&flags[1],"START",5,FLAG_OPTION_HEADER);
RX_FLAG_INIT(&flags[2],"END",3,FLAG_OPTION_STRONG_ENDER);
RX_FLAG_INIT(&flags[3],"12345",5,FLAG_OPTION_STRONG_UNIQUE);
mac=RxMac_Create(flags,4,buffer,BUF_SIZE,NULL,onGetHeader,onFlushed);
}
//協(xié)議示例2:
//幀頭:START
//幀頭后的第1個(gè)字符表示后面還要接收多少個(gè)字符1-9,'4'表示4個(gè),如果不是數(shù)字或?yàn)?0',則等待幀尾
//幀尾:END
//特殊串:NOW
//
staticvoidprotocol2_init(void){
RX_FLAG_INIT(&flags[0],"START",5,FLAG_OPTION_HEADER);
RX_FLAG_INIT(&flags[1],"END",3,FLAG_OPTION_ENDER);
RX_FLAG_INIT(&flags[2],"NOW",3,FLAG_OPTION_UNIQUE);
mac=RxMac_Create(flags,3,buffer,BUF_SIZE,NULL,onGetHeader2,onFlushed);
}
/*
*********************************************************************************************************
*CALLBACKFUNCITON
*********************************************************************************************************
*/

staticvoidonGetData(RxMacsender,uint8_t*pCurChar,uint16_tbytesCnt){
//因?yàn)榘l(fā)現(xiàn)幀頭后才掛載事件,所以下一次回掉正好是說明字符數(shù)的那個(gè)字符,否則還得根據(jù)bytesCnt來判斷當(dāng)前位置
RxMac_SetOnFeeded(sender,NULL);
if(*pCurChar>'0'&&*pCurChar<=?'9'?){
????//?bytesCnt是當(dāng)前收到了多少個(gè)字符,所以接收區(qū)大小為當(dāng)前字符數(shù)加上還要接收的
????RxMac_SetRxSize(sender,*pCurChar?-?'0'?+?bytesCnt);
??}
}
static?void?onFlushed(RxMac?sender,RxMacPtr?buf,uint16_t?len,RxState?state,RxFlag?HorU,RxFlag?Ender){
??buf[len]?=?'?';
??printf("
Flushed:");
??if(state.headerFound)
????printf("headerFound,");
??if(state.enderFound)
????printf("enderFound,");
??if(state.isFull)
????printf("full,");
??if(state.uniqueFound)
????printf("unique,");
??printf("
Datas:%s
",buf);
??RxMac_SetRxSize(sender,BUF_SIZE);
}
static?void?onGetHeader(RxMac?sender,RxFlag?flag){
??printf("
FoundHeader:%s
",flag->pBuf);
}
staticvoidonGetHeader2(RxMacsender,RxFlagflag){
printf("
FoundHeader:%s
",flag->pBuf);
RxMac_SetOnFeeded(sender,onGetData);
}
/*
*********************************************************************************************************
*MAINFUNCTION
*********************************************************************************************************
*/

voidmain(void){
//選擇想要實(shí)驗(yàn)的協(xié)議來初始化
protocol1_init();
//protocol2_init();
while(1){
c=getchar();
//回顯
putchar(c);
RxMac_FeedData(mac,c);
}
}

示例協(xié)議1測(cè)試結(jié)果6ff5a622-ccde-11ed-bfe3-dac502259ad0.png

示例協(xié)議2測(cè)試結(jié)果701c574a-ccde-11ed-bfe3-dac502259ad0.png可以看到,第二個(gè)協(xié)議中我們通過改變緩沖區(qū)大小成功控制了數(shù)據(jù)包的長度。

雖然這里的示例都是基于ASCII的,但這只是為了觀察起來方便,普通的基于二進(jìn)制的協(xié)議也是可以使用這個(gè)模塊的。

v1.0代碼

舊版代碼中引用了我自己寫的(現(xiàn)已棄用)環(huán)形緩沖區(qū)模塊:
https://blog.csdn.net/lin_strong/article/details/73604561

接收機(jī)代碼

頭文件

/*
*********************************************************************************************************
*
*
*UniversalReceiveStateMachine
*通用接收狀態(tài)機(jī)
*
*File:RxMac.h
*
*By:LinShijun(https://blog.csdn.net/lin_strong)
*Date:2018/05/29
*version:1.0
*History:2018/05/29theprototype
*NOTE(s):1.thereceiveprocesshastwobasicstate
*A.preRx:whenhaven'tfoundanyheader,theRxMacwillsearchfortheunique
*flag,headerandstrong-ender.Onlywhenaheaderisfoundwillcome
*tonextstep.
*B.Rxing:theRxMacwillputthesuccessivebytesintothebuffer,andsearch
*forthestrong-unique,strong-header,ender.
*2.themoduleisdrivedbytheRxMac_FeedData(),usershouldgetthethechar
*fromdatastreamandpassthedataonebyonetotheRxMacthroughRxMac_FeedData()
*3.eachtimeRxMacfindaframe(completeorincomplete),itwillcalltheonFlushed
*tonotifytheresults;usercanjudgetheframethroughthestateparameter;
*state.headerFound==1:findanyheader,theheaderispassedbypHorU
*state.enderFound==1:findanyender,theenderispassedbypEnder
*state.isFull==1:thebufferisfull,maybeyoushouldcheckheaderFound
*toseewhetheraheaderhasbeenfound.
*state.uniqueFound==1:findanyuniqueflag.Inthiscase,otherparameterswill
*alwaysbe0&thedatasinthebufferwillbetheflag.
*4.Tousethismodule,foreachreceivemachine:
*A.allocatethespaceforbuffer,RxMac&FLAGS
*RX_MAC_Mac;
*RX_FLAGflags[2];
*INT8Ubuf[300];
*B.settheflagsaccordingtotheprotocol,definethecallbackfuncitons
*accordingtoyourneed.
*staticvoidonGetHeader(pRX_MACsender,pRX_FLAGpFlag){......};
*staticvoidonFlushed(pRX_MACsender,pRB_BYTEpBuf,INT16Ulen,
*RX_STATEstate,pRX_FLAGpHorU,pRX_FLAGpEnder){......};
*constINT8UHeaderFlag[]="Header";
*constINT8UEnderFlag[]="
";
*RX_FLAG_INIT(flags,HeaderFlag,StrSize(HeaderFlag),FLAG_OPTION_HEADER);
*RX_FLAG_INIT(&flags[1],EnderFlag,StrSize(EnderFlag),FLAG_OPTION_ENDER|
*FLAG_OPTION_NOTFILL_ENDER);
*C.initthereceivemachine:
*RxMac_Init(&_Mac,flags,2,6,buf,300,NULL,onGetHeader,onFlushed);
*D.feedthereceivemachine:
*while(1){
*c=GetNextChar();
*RxMac_FeedData(&_Mac,c);
*}
*********************************************************************************************************
*/

#ifndefRX_MAC_H
#defineRX_MAC_H


/*
*********************************************************************************************************
*INCLUDES
*********************************************************************************************************
*/
#include"RingQueue.h"
#include

//typedefunsignedcharINT8U;
//typedefunsignedshortINT16U;

/*
*********************************************************************************************************
*ADDRESSINGMODE尋址模式
*********************************************************************************************************
*/
//theaddressingmodeforbuffer
#defineRXMAC_BUF_ADDRESSING_MODERQ_ADDRESSING_MODE

typedefINT8URB_BYTE;
typedefRB_BYTE*RXMAC_BUF_ADDRESSING_MODEpRB_BYTE;
/*
*********************************************************************************************************
*CONFIGURATION配置
*********************************************************************************************************
*/

#defineRXMAC_ARGUMENT_CHECK_ENTRUE
#defineRXMAC_NOTFILL_ENTRUE

#defineRXMAC_ONFEEDED_ENTRUE//TRUE:enabletheonFeededfunction.

#defineRXMAC_SINGLETON_ENFALSE//TRUE:enablesingletonpattern,soargumentpRxMacofinterfaces
//isuseless,anduserdon'tneedtoallocatespaceforRX_MAC,
//butyoustillneedtoallocatebufferandcallinit();

/*
*********************************************************************************************************
*CONST
*********************************************************************************************************
*/

#defineRXMAC_ERR_NONE0
#defineRXMAC_ERR_ARGUMENT1
#defineRXMAC_ERR_POINTERNULL2
#defineRXMAC_ERR_UNKNOWN3
#defineRXMAC_ERR_INIT4
/*
*********************************************************************************************************
*TYPEDEFINITION
*********************************************************************************************************
*/

//structofRX_FLAG.option
/*typedefstructFLAG_OPTION{
unsignedintisHeader:1;//1:theflagistheheadoftheframe
unsignedintstrong_H:1;//1:strong-header,RxMacwill
unsignedintnotfill_H:1;//0:filltheflagintothebufferwhenfoundasheader
unsignedintisEnder:1;//1:theflagistheendoftheframe
unsignedintstrong_E:1;//
unsignedintnotfill_E:1;//0:filltheflagintothebufferwhenfoundasender
unsignedintisUnique:1;//1:theflagisauniqueflagwhichistreatedassingleframe.
unsignedintstrong_U:1;//0:whenreceivingaframe,RxMacwillnot
};//*/

//接收標(biāo)志位
typedefstructrx_flag{
INT8Uconst*pBuf;
INT8Ulen;
INT8Uoption;
}RX_FLAG,*pRX_FLAG;

//normalheader,RxMacwillonlycheckitinStepA
#defineFLAG_OPTION_HEADER0x01
//strongheader,RxMacwillalwayscheckit.
#defineFLAG_OPTION_STRONG_HEADER0x03
//theheaderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisheader)
#defineFLAG_OPTION_NOTFILL_HEADER0x04
//normalender,RxMacwillonlycheckitinStepB
#defineFLAG_OPTION_ENDER0x08
//strongheader,RxMacwillalwayscheckit.
#defineFLAG_OPTION_STRONG_ENDER0x18
//theenderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisender)
#defineFLAG_OPTION_NOTFILL_ENDER0x20
//normalunique,RxMacwillonlycheckitinStepA
#defineFLAG_OPTION_UNIQUE0x40
//strongunique,RxMacwillalwayscheckit.
#defineFLAG_OPTION_STRONG_UNIQUE0xC0

typedefstructrx_state{
unsignedintheaderFound:1;//1:havegetheader
unsignedintenderFound:1;//1:havegetender
unsignedintisFull:1;//1:thebufferisfull
unsignedintuniqueFound:1;//1:thisisuniqueflag.
}RX_STATE;

typedefstructrx_macRX_MAC,*pRX_MAC;
typedefvoid(*RXMAC_FLUSH_EVENT)(pRX_MACsender,pRB_BYTEpBuf,INT16Ulen,RX_STATEstate,pRX_FLAGpHorU,pRX_FLAGpEnder);
typedefvoid(*RXMAC_FLAG_EVENT)(pRX_MACsender,pRX_FLAGpFlag);
typedefvoid(*RXMAC_FILTER)(pRX_MACsender,pRB_BYTEpCurChar,INT16UbytesCnt);

structrx_mac{
RING_QUEUEFlagQueue;//用于判斷標(biāo)志串的環(huán)形緩沖區(qū)對(duì)象

pRX_FLAGFlags;//標(biāo)志數(shù)組
INT8UFlagsCnt;//標(biāo)志數(shù)組的個(gè)數(shù)
RX_STATEstate;//接收的狀態(tài)(內(nèi)部使用)
pRX_FLAGpHorU;//內(nèi)部使用

pRB_BYTEpRxBuf;//存放數(shù)據(jù)的緩沖區(qū)
INT16URxBufSize;//緩沖區(qū)的長度

pRB_BYTEpCur;//指向緩沖區(qū)內(nèi)下一個(gè)填充字符的位置

RXMAC_FILTERonFeeded;//當(dāng)被喂字符時(shí)觸發(fā),返回指向緩沖區(qū)中剛剛喂進(jìn)來的字符的指針以及是緩沖區(qū)內(nèi)的第幾個(gè)字符

RXMAC_FLAG_EVENTonGetHeader;//獲得頭標(biāo)志位時(shí)觸發(fā)。
RXMAC_FLUSH_EVENTonFlushed;//回調(diào)函數(shù)
};


/*
*********************************************************************************************************
*FUNCTIONDECLARATION
*********************************************************************************************************
*/
//tosettheflag'soption
//pbufpointertotheflagbuffer
//bufSizesizeofflag
//optseeFLAG_OPTION_XXXXX
#defineRX_FLAG_INIT(pFlag,pbuf,bufSize,opt)
(pFlag)->pBuf=(pbuf);(pFlag)->len=(bufSize);(pFlag)->option=(opt);

//toinittheRxMac
INT8URxMac_Init(pRX_MACpRxMac,//需要用戶自己申請(qǐng)個(gè)UNI_RX_MACHINE對(duì)象的空間
RX_FLAGFlags[],INT8UFlagsCnt,INT8UmaxLenOfFlags,//提供標(biāo)志字符串的數(shù)組
pRB_BYTEpBuf,INT16UBufLen,//用戶需要提供緩沖區(qū)(緩存區(qū)大小起碼應(yīng)該要能
//放的下最長的Flag+最長的幀,最后部分會(huì)分配給RQ)
RXMAC_FILTERonFeeded,//在每次被Feed時(shí)觸發(fā)
RXMAC_FLAG_EVENTonGetHeader,//獲得頭標(biāo)志位時(shí)觸發(fā)。
RXMAC_FLUSH_EVENTonFlushed//收到一幀數(shù)據(jù)時(shí)的回調(diào)函數(shù)
);
//向接收機(jī)內(nèi)喂字節(jié)
voidRxMac_FeedData(pRX_MACpRxMac,INT8Uc);
//重置接收區(qū)長度為最長那個(gè)長度
INT8URxMac_ResetRxSize(pRX_MACpRxMac);
//設(shè)置最大接收到多少個(gè)字節(jié)
INT8URxMac_SetRxSize(pRX_MACpRxMac,INT16Usize);
//重置接收機(jī)的狀態(tài)
INT8URxMac_ResetState(pRX_MACpRxMac);
//強(qiáng)制接收機(jī)flush
INT8URxMac_Flush(pRX_MACpRxMac);
//設(shè)置onFeeded
INT8URxMac_SetOnFeeded(pRX_MACpRxMac,RXMAC_FILTERonFeeded);
//設(shè)置onGetHeader
INT8URxMac_SetOnGetHeader(pRX_MACpRxMac,RXMAC_FLAG_EVENTonGetHeader);
//設(shè)置onFlushed
INT8URxMac_SetOnFlushed(pRX_MACpRxMac,RXMAC_FLUSH_EVENTonFlushed);

#endif//ofRX_MAC_H

源文件:

/*
*********************************************************************************************************
*
*
*UniversalReceiveStateMachine
*通用接收狀態(tài)機(jī)
*
*File:RxMac.c
*
*By:LinShijun(https://blog.csdn.net/lin_strong)
*Date:2018/05/29
*version:1.0
*History:
*NOTE(s):
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*INCLUDES
*********************************************************************************************************
*/
#include"RxMac.h"

#include
#include
/*
*********************************************************************************************************
*CONSTANT
*********************************************************************************************************
*/
//normalheader,RxMacwillonlycheckitinStepA
#defineFLAG_OPTBIT_HEADER0x01
//strongheader,RxMacwillalwayscheckit.
#defineFLAG_OPTBIT_STRONG_HEADER0x02
//theheaderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisheader)
#defineFLAG_OPTBIT_NOTFILL_HEADER0x04
//normalender,RxMacwillonlycheckitinStepB
#defineFLAG_OPTBIT_ENDER0x08
//strongheader,RxMacwillalwayscheckit.
#defineFLAG_OPTBIT_STRONG_ENDER0x10
//theenderwillnotbefilledintobufferwhenfound.(onlyvalidwhenisender)
#defineFLAG_OPTBIT_NOTFILL_ENDER0x20
//normalunique,RxMacwillonlycheckitinStepA
#defineFLAG_OPTBIT_UNIQUE0x40
//strongunique,RxMacwillalwayscheckit.
#defineFLAG_OPTBIT_STRONG_UNIQUE0x80

#defineSTATEMASK_STEPA(FLAG_OPTBIT_HEADER|FLAG_OPTBIT_UNIQUE|FLAG_OPTBIT_STRONG_ENDER)
#defineSTATEMASK_STEPB(FLAG_OPTBIT_STRONG_UNIQUE|FLAG_OPTBIT_ENDER|FLAG_OPTBIT_STRONG_HEADER)
#defineFLAGMASK_USUHSH(FLAG_OPTBIT_HEADER|FLAG_OPTBIT_STRONG_HEADER|FLAG_OPTION_UNIQUE|FLAG_OPTBIT_STRONG_UNIQUE)

/*
*********************************************************************************************************
*LOCALFUNCITONDECLARATION
*********************************************************************************************************
*/
#if(RXMAC_SINGLETON_EN==FALSE)
#define_pRxMacpRxMac
#else
staticRX_MAC_RxMac;
#define_pRxMac(&_RxMac)
#endif

#define_FlagQueue(_pRxMac->FlagQueue)
#define_Flags(_pRxMac->Flags)
#define_FlagsCnt(_pRxMac->FlagsCnt)
#define_state(_pRxMac->state)
#define_stateByte(*(INT8U*)(&_state))
#define_pHorU(_pRxMac->pHorU)
#define_pRxBuf(_pRxMac->pRxBuf)
#define_RxBufSize(_pRxMac->RxBufSize)
#define_pCur(_pRxMac->pCur)
#define_onFeeded(_pRxMac->onFeeded)
#define_onGetHeader(_pRxMac->onGetHeader)
#define_onFlushed(_pRxMac->onFlushed)
#define_isRxBufFull()((_pCur-_pRxBuf)>=_RxBufSize)


//因?yàn)椴荒鼙WC用戶把數(shù)據(jù)放在非分頁區(qū),只好自己實(shí)現(xiàn)一個(gè),實(shí)際使用中如果確定在非分頁區(qū)可以把下面的宏替換為庫函數(shù)memcpy
staticpRB_BYTE_memcpy_internal(pRB_BYTEdest,pRB_BYTEsrc,size_tn);
#define_memcpy(dest,src,n)_memcpy_internal(dest,src,n)
//沖刷緩沖區(qū)
staticvoid_flush(pRX_MACpRxMac,pRX_FLAGender);
//往接收機(jī)緩沖區(qū)內(nèi)放數(shù)據(jù)
staticvoid_BufIn(pRX_MACpRxMac,pRB_BYTEpBuf,INT16Ulen);

/*
*********************************************************************************************************
*RxMac_Init()
*
*Description:ToinitializeaRxMac.初始化接收機(jī)
*
*Arguments:pRxMacpointertotheRxMacstruct;指向接收機(jī)結(jié)構(gòu)體的指針
*Flagspointertotheflags(anarray);指向標(biāo)志串(數(shù)組)的指針
*FlagsCntthecountoftheflags;有多少個(gè)標(biāo)志串;
*maxLenOfFlagsthemaxlengthofflags;標(biāo)志字符串最長的長度
*pBufpointertothebufferprovidedtotheRxMac;提供給接收機(jī)使用的緩存
*BufLenthesizeofthebuffer.緩存的大小
*onFeededthecallbackfuncthatwillbecalledwhenfeeded.
*每次被feed時(shí)會(huì)調(diào)用的回調(diào)函數(shù),如改變對(duì)應(yīng)數(shù)據(jù)值會(huì)影響標(biāo)志位的判斷
*onGetHeaderthecallbackfuncthatwillbecalledwhenfindaheader.
*當(dāng)發(fā)現(xiàn)幀頭時(shí)會(huì)調(diào)用的回調(diào)函數(shù)
*onFlushedthecallbackfuncthatwillbecalledwhenflushed.
*當(dāng)Flush時(shí)會(huì)調(diào)用的回調(diào)函數(shù)
*
*Return:RXMAC_ERR_NONEifsuccess
*RXMAC_ERR_ARGUMENTifthelengthoflongestFlagsbiggerthanBuflen,oroneofthemis0
*RXMAC_ERR_POINTERNULLifemptypointer
*
*Note(s):sizeofbuffershouldbiggerthanthelongestflagplusthelongestframe
*thatmaybereceived(soatleast2*maxLenOfFlags).
*thebufferisallocateasfollow:
*<----------------------??BufLen??---------------------->
*|RxBuffer||
*<-------------?RxBufSize?------------><-maxLenOfFlags->
*
*voidonGetHeader(pRX_MACsender,pRX_FLAGpFlag):
*senderthepointertotheRxMacwhichcallthisfunction
*pFlagtheheadermatched
*
*voidonFeeded(pRX_MACsender,pRB_BYTEpCurChar,INT16UbytesCnt):
*senderthepointertotheRxMacwhichcallthisfunction
*pCurCharpointtothecharinthebufferjustreceived.
*bytesCntthenumberofbytesinthebufferincludingthecharjustfeeded.
*
*voidonFlushed(pRX_MACsender,pRB_BYTEpBuf,INT16Ulen,RX_STATEstate,pRX_FLAGpHorU,
*pRX_FLAGpEnder);
*senderthepointertotheRxMacwhichcallthisfunction
*pBufthepointertotheframe.
*lenthelengthofframe.
*statethestateofframe.
*pHorUpointtotheheaderflagifstate.headerFound==1,oruniqueflagif
*state.uniqueFound==1.
*pEnderpointtotheenderflagifstate.enderFound==1.
*********************************************************************************************************
*/
INT8URxMac_Init
(pRX_MACpRxMac,RX_FLAGFlags[],INT8UFlagsCnt,INT8UmaxLenOfFlags,pRB_BYTEpBuf,INT16UBufLen,
RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed){
//INT8UmaxLen=0;
INT8Ui;
#if(RXMAC_ARGUMENT_CHECK_EN)
if(
#if(!RXMAC_SINGLETON_EN)
_pRxMac==NULL||
#endif
Flags==NULL||pBuf==NULL)
returnRXMAC_ERR_POINTERNULL;
#endif
//findoutthemaxlengthofflags.
//for(i=0;imaxLen)
//maxLen=Flags[i].len;
//}
#if(RXMAC_ARGUMENT_CHECK_EN)
if(maxLenOfFlags==0||(maxLenOfFlags*2)>BufLen||BufLen==0||FlagsCnt==0||
maxLenOfFlags==0)
returnRXMAC_ERR_ARGUMENT;
#endif
BufLen-=maxLenOfFlags;
//把buffer的最后一段分配給環(huán)形緩沖區(qū)
RingQueueInit(&_FlagQueue,pBuf+BufLen,maxLenOfFlags,&i);
_Flags=Flags;
_FlagsCnt=FlagsCnt;
_stateByte=0;
_pHorU=NULL;
_pRxBuf=pBuf;
_RxBufSize=BufLen;
_pCur=pBuf;
_onFeeded=onFeeded;
_onGetHeader=onGetHeader;
_onFlushed=onFlushed;
returnRXMAC_ERR_NONE;
}
/*
*********************************************************************************************************
*RxMac_FeedData()
*
*Description:TofeedRxMacthenextchar.用于給接收機(jī)下一個(gè)字符
*
*Arguments:pRxMacpointertotheRxMacstruct;指向接收機(jī)結(jié)構(gòu)體的指針
*cthechartofeed;下一個(gè)字符
*
*Return:
*
*Note(s):
*********************************************************************************************************
*/
voidRxMac_FeedData(pRX_MACpRxMac,INT8Uc){
INT8Ui,mask;
pRX_FLAGpFlag=NULL;
#if(RXMAC_ONFEEDED_EN)
pRB_BYTEpCurChar=_pCur;
#endif
#if(RXMAC_ARGUMENT_CHECK_EN&&!RXMAC_SINGLETON_EN)
if(_pRxMac==NULL)
return;
#endif
*_pCur++=c;//填入緩沖區(qū)
#if(RXMAC_ONFEEDED_EN)
if(_onFeeded!=NULL)
_onFeeded(_pRxMac,pCurChar,_pCur-_pRxBuf);
RingQueueIn(&_FlagQueue,*pCurChar,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&i);
#else
RingQueueIn(&_FlagQueue,c,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&i);
#endif
//_state.headerFound==1說明在等待幀尾,否則在等待幀頭
mask=(_state.headerFound)?STATEMASK_STEPB:STATEMASK_STEPA;
//尋找匹配的標(biāo)志串
for(i=0;i=0)){
RingQueueClear(&_FlagQueue);
pFlag=&_Flags[i];
break;
}
}
//如果沒有發(fā)現(xiàn)標(biāo)志串,檢查下有沒滿了,滿了就Flush
if(pFlag==NULL){
if(_isRxBufFull()){
_state.isFull=1;
_flush(_pRxMac,NULL);
}
return;
}
//這4種標(biāo)志串要_flush掉前面的東西
if(pFlag->option&FLAGMASK_USUHSH){
_pCur-=pFlag->len;
_flush(_pRxMac,NULL);
_pHorU=pFlag;
}
//如果是幀頭的處理
if(pFlag->option&(FLAG_OPTION_STRONG_HEADER|FLAG_OPTION_HEADER)){
#if(RXMAC_NOTFILL_EN==TRUE)
if(!(pFlag->option&FLAG_OPTION_NOTFILL_HEADER))
#endif
_BufIn(_pRxMac,(pRQTYPE)pFlag->pBuf,pFlag->len);
_state.headerFound=1;
if(_onGetHeader!=NULL)
_onGetHeader(_pRxMac,pFlag);
return;
}
//如果是Unique的處理
if(pFlag->option&(FLAG_OPTION_STRONG_UNIQUE|FLAG_OPTION_UNIQUE)){
_state.uniqueFound=1;
_BufIn(_pRxMac,(pRQTYPE)pFlag->pBuf,pFlag->len);
_flush(_pRxMac,NULL);
}else{//能到這里說明是幀尾
_state.enderFound=1;
#if(RXMAC_NOTFILL_EN==TRUE)
if(pFlag->option&FLAG_OPTION_NOTFILL_ENDER)
_pCur-=pFlag->len;
#endif
_flush(_pRxMac,pFlag);
}
return;
}
/*
*********************************************************************************************************
*RxMac_ResetRxSize()
*
*Description:resetthesizeofRxBuftothemaxsize.重置接收緩沖區(qū)
*
*Arguments:pRxMacpointertotheRxMacstruct;指向接收機(jī)結(jié)構(gòu)體的指針
*
*Return:RXMAC_ERR_NONEifSuccess;
*RXMAC_ERR_POINTERNULLifpRxMac==NULL
*RXMAC_ERR_INITifRxMachasn'tinitedoranyerrorininitialization
*Note(s):
*********************************************************************************************************
*/
INT8URxMac_ResetRxSize(pRX_MACpRxMac){
intsize;
#if(RXMAC_ARGUMENT_CHECK_EN&&!RXMAC_SINGLETON_EN)
if(_pRxMac==NULL)
returnRXMAC_ERR_POINTERNULL;
#endif
size=_FlagQueue.RingBuf-_pRxBuf;
#if(RXMAC_ARGUMENT_CHECK_EN)
if(size0)
*p++=*src++;
returndest;
}

staticvoid_BufIn(pRX_MACpRxMac,pRB_BYTEpBuf,INT16Ulen){
_memcpy(_pCur,pBuf,len);
_pCur+=len;
}

staticvoid_flush(pRX_MACpRxMac,pRX_FLAGender){
//觸發(fā)回調(diào)
if(_pCur-_pRxBuf>0&&_onFlushed!=NULL)
_onFlushed(_pRxMac,_pRxBuf,_pCur-_pRxBuf,_state,_pHorU,ender);
//復(fù)位接收機(jī)
_pCur=_pRxBuf;
_stateByte=0;
_pHorU=NULL;
}

測(cè)試/示例代碼

/*
*********************************************************************************************************
*uC/OS-II
*TheReal-TimeKernel
*Framework
*
*By:LinShijun
*Note:ThisisaframeworkforuCos-iiprojectwithonlyS12CPU,nonefloat,bankedmemorymodel.
*Youcanusethisframeworkwithsamemodificationasthestartpointofyourproject.
*I'veremovedtheos_probemodule,sinceIthoughtituselessinmostcase.
*Thisframeworkisadaptedfromtheofficialrelease.
*********************************************************************************************************
*/

#include"includes.h"
#include"SCI_def.h"
#include"RxMac.h"
/*
*********************************************************************************************************
*STACKSPACEDECLARATION
*********************************************************************************************************
*/
staticOS_STKAppTaskStartStk[APP_TASK_START_STK_SIZE];

/*
*********************************************************************************************************
*TASKFUNCTIONDECLARATION
*********************************************************************************************************
*/

staticvoidAppTaskStart(void*p_arg);

/*
*********************************************************************************************************
*CALLBACKFUNCITON
*********************************************************************************************************
*/
voidonGetData(pRX_MACsender,pRB_BYTEpCurChar,INT16UbytesCnt){
//因?yàn)榘l(fā)現(xiàn)幀頭后才掛載事件,所以下一次回掉正好是說明字符數(shù)的那個(gè)字符,否則還得根據(jù)bytesCnt來判斷當(dāng)前位置
RxMac_SetOnFeeded(sender,NULL);
if(*pCurChar>'0'&&*pCurChar<=?'9'?){
????//?bytesCnt是當(dāng)前收到了多少個(gè)字符,所以接收區(qū)大小為當(dāng)前字符數(shù)加上還要接收的
????RxMac_SetRxSize(sender,*pCurChar?-?'0'?+?bytesCnt);
??}
}
void?onFlushed(pRX_MAC?sender,pRB_BYTE?pBuf,INT16U?len,RX_STATE?state,pRX_FLAG?pHorU,pRX_FLAG?pEnder){
??SCI_PutCharsB(SCI0,"
Flushed:",9,0);
??if(state.headerFound)
????SCI_PutCharsB(SCI0,"headerFound,",12,0);
??if(state.enderFound)
????SCI_PutCharsB(SCI0,"enderFound,",11,0);
??if(state.isFull)
????SCI_PutCharsB(SCI0,"full,",5,0);
??if(state.uniqueFound)
????SCI_PutCharsB(SCI0,"unique,",7,0);
??SCI_PutCharsB(SCI0,"
Datas:",7,0);
??SCI_PutCharsB(SCI0,pBuf,len,0);
??SCI_PutCharsB(SCI0,"
",1,0);
??RxMac_ResetRxSize(sender);
}
void?onGetHeader(pRX_MAC?sender,pRX_FLAG?pFlag){
??SCI_PutCharsB(SCI0,"
FoundHeader:",13,0);
??SCI_PutCharsB(SCI0,pFlag->pBuf,pFlag->len,0);
SCI_PutCharsB(SCI0,"
",1,0);
}
voidonGetHeader2(pRX_MACsender,pRX_FLAGpFlag){
SCI_PutCharsB(SCI0,"
FoundHeader:",13,0);
SCI_PutCharsB(SCI0,pFlag->pBuf,pFlag->len,0);
SCI_PutCharsB(SCI0,"
",1,0);
RxMac_SetOnFeeded(sender,onGetData);
}
/*
*********************************************************************************************************
*FLAGS
*********************************************************************************************************
*/
RX_MAC_rxmac;
#defineBUF_SIZE20
INT8Ubuffer[BUF_SIZE];
RX_FLAGflags[4];

//協(xié)議示例1:
//幀頭:HEADER或者START
//強(qiáng)幀尾:END
//強(qiáng)特殊串:12345
//
staticvoidprotocol1_init(){
RX_FLAG_INIT(&flags[0],"HEADER",6,FLAG_OPTION_HEADER);
RX_FLAG_INIT(&flags[1],"START",5,FLAG_OPTION_HEADER);
RX_FLAG_INIT(&flags[2],"END",3,FLAG_OPTION_STRONG_ENDER);
RX_FLAG_INIT(&flags[3],"12345",5,FLAG_OPTION_STRONG_UNIQUE);
RxMac_Init(&_rxmac,flags,4,6,buffer,BUF_SIZE,NULL,onGetHeader,onFlushed);
}
//協(xié)議示例2:
//幀頭:START
//幀頭后的第1個(gè)字符表示后面還要接收多少個(gè)字符1-9,'4'表示4個(gè),如果不是數(shù)字或?yàn)?0',則等待幀尾
//幀尾:END
//特殊串:NOW
//
staticvoidprotocol2_init(){
RX_FLAG_INIT(&flags[0],"START",5,FLAG_OPTION_HEADER);
RX_FLAG_INIT(&flags[1],"END",3,FLAG_OPTION_ENDER);
RX_FLAG_INIT(&flags[2],"NOW",3,FLAG_OPTION_UNIQUE);
RxMac_Init(&_rxmac,flags,3,5,buffer,BUF_SIZE,NULL,onGetHeader2,onFlushed);
}

/*
*********************************************************************************************************
*MAINFUNCTION
*********************************************************************************************************
*/


voidmain(void){
INT8Uerr;
BSP_IntDisAll();/*DisableALLinterruptstotheinterruptcontroller*/
OSInit();/*InitializeuC/OS-II*/

err=OSTaskCreate(AppTaskStart,
NULL,
(OS_STK*)&AppTaskStartStk[APP_TASK_START_STK_SIZE-1],
APP_TASK_START_PRIO);
OSStart();
}

staticvoidAppTaskStart(void*p_arg)
{
INT8Uc,err;
(void)p_arg;/*Preventcompilerwarning*/
BSP_Init();
SCI_Init(SCI0);
SCI_EnableTrans(SCI0);
SCI_EnableRecv(SCI0);
SCI_EnableRxInt(SCI0);
SCI_BufferInit();
//選擇想要實(shí)驗(yàn)的協(xié)議來初始化
protocol1_init();
//protocol2_init();
while(DEF_TRUE)
{
//獲取下一個(gè)字符
c=SCI_GetCharB(SCI0,0,&err);
//回顯
SCI_PutCharB(SCI0,c,0);
//喂給接收機(jī)
RxMac_FeedData(&_rxmac,c);
}
}

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 模塊
    +關(guān)注

    關(guān)注

    7

    文章

    2613

    瀏覽量

    47012
  • 嵌入式
    +關(guān)注

    關(guān)注

    5046

    文章

    18817

    瀏覽量

    298562
  • 接收機(jī)
    +關(guān)注

    關(guān)注

    8

    文章

    1158

    瀏覽量

    53171
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4237

    瀏覽量

    61969
  • 狀態(tài)機(jī)
    +關(guān)注

    關(guān)注

    2

    文章

    489

    瀏覽量

    27394

原文標(biāo)題:[嵌入式開發(fā)模塊]通用接收狀態(tài)機(jī)模塊

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式軟件開發(fā)中常用的狀態(tài)機(jī)編程實(shí)現(xiàn)

    嵌入式軟件開發(fā)中,狀態(tài)機(jī)編程是一個(gè)十分重要的編程思想,它也是嵌入式開發(fā)中一個(gè)常用的編程框架。掌握了狀態(tài)機(jī)編程思想,可以更加邏輯清晰的實(shí)現(xiàn)復(fù)
    發(fā)表于 09-06 10:25 ?1763次閱讀

    基于狀態(tài)機(jī)嵌入式系統(tǒng)開發(fā)

    給大家分享下,基于狀態(tài)機(jī)嵌入式系統(tǒng)開發(fā),慢慢看吧
    發(fā)表于 12-22 19:44

    嵌入式開發(fā)

    嵌入式開發(fā)就是指在嵌入式操作系統(tǒng)下進(jìn)行開發(fā)嵌入式Linux是以Linux為基礎(chǔ)的嵌入式作業(yè)系統(tǒng)。這里提供了
    發(fā)表于 12-20 13:21
    <b class='flag-5'>嵌入式開發(fā)</b>

    [嵌入式開發(fā)板]iTOP-4412以模塊的方式編譯內(nèi)核驅(qū)動(dòng)

    [嵌入式開發(fā)板]iTOP-4412以模塊的方式編譯驅(qū)動(dòng)。
    發(fā)表于 03-15 09:31 ?21次下載

    嵌入式軟件中狀態(tài)機(jī)的抽象與實(shí)現(xiàn)

    文中提出了 在嵌入式軟件中把狀態(tài)機(jī)作為一個(gè)獨(dú)立模塊從控制模塊中抽象出來的思想 , 描述了 抽象出來的狀態(tài)機(jī)
    發(fā)表于 03-22 15:47 ?1次下載

    有限狀態(tài)機(jī)嵌入式系統(tǒng)中的實(shí)現(xiàn)及應(yīng)用

    如何使嵌入式軟件代碼更加可靠 增強(qiáng)程序的可維護(hù)性 一直以來都是嵌入式程序員追 求的目標(biāo)。論述了有限狀態(tài)機(jī)的原理和其實(shí)現(xiàn)方法;采用狀態(tài)機(jī)方法編寫了一個(gè)按鍵掃描程序介紹了
    發(fā)表于 03-22 15:40 ?1次下載

    LabVIEW ARM嵌入式開發(fā)模塊的詳細(xì)介紹和使用手冊(cè)中文資料概述

    LabVIEW ARM嵌入式開發(fā)模塊是一個(gè)完整的圖形化開發(fā)環(huán)境,由NI聯(lián)合Keil公司開發(fā)而成,使用這個(gè)模塊對(duì)ARM芯片
    發(fā)表于 06-19 08:00 ?16次下載
    LabVIEW ARM<b class='flag-5'>嵌入式開發(fā)</b><b class='flag-5'>模塊</b>的詳細(xì)介紹和使用手冊(cè)中文資料概述

    嵌入式開發(fā)的產(chǎn)品有哪些_嵌入式開發(fā)的流程

    本文主要闡述了嵌入式開發(fā)的產(chǎn)品,其次介紹了嵌入式開發(fā)的流程。
    發(fā)表于 08-31 15:38 ?1.1w次閱讀

    嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試

    嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試(嵌入式開發(fā)和硬件開發(fā))-嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊
    發(fā)表于 07-30 13:55 ?9次下載
    <b class='flag-5'>嵌入式</b>LINUX系統(tǒng)內(nèi)核和內(nèi)核<b class='flag-5'>模塊</b>調(diào)試

    嵌入式開發(fā)(一):嵌入式開發(fā)新手入門

    本篇文章整理下嵌入式開發(fā)中一些入門的基礎(chǔ)技能,都是根據(jù)以往的工程經(jīng)驗(yàn)整理,適用于之前沒做過嵌入式開發(fā)的新手。嵌入式開發(fā)流程一般如下,一般是在PC機(jī)的Windows系統(tǒng)下安裝Ubuntu
    發(fā)表于 10-14 10:58 ?79次下載
    <b class='flag-5'>嵌入式開發(fā)</b>(一):<b class='flag-5'>嵌入式開發(fā)</b>新手入門

    嵌入式開發(fā)資料免費(fèi)分享

    嵌入式開發(fā)資料免費(fèi)分享嵌入式工程師經(jīng)驗(yàn)分享:如何學(xué)習(xí)嵌入式開發(fā)截取文檔部分學(xué)習(xí)嵌入式工程師經(jīng)驗(yàn)分享的資料分享給大家,文檔上從、嵌入式系統(tǒng)的概
    發(fā)表于 10-21 11:07 ?46次下載
    <b class='flag-5'>嵌入式開發(fā)</b>資料免費(fèi)分享

    嵌入式狀態(tài)機(jī)的設(shè)置

    狀態(tài)機(jī)嵌入式軟件中隨處可見,可能你會(huì)說狀態(tài)機(jī)有什么難的,不就是 switch 嗎?
    的頭像 發(fā)表于 11-02 09:04 ?1001次閱讀

    嵌入式狀態(tài)機(jī)的編程優(yōu)點(diǎn)分析

    嵌入式狀態(tài)機(jī)編程是真的好用,寫出來的程序結(jié)構(gòu)非常清晰!所以平時(shí)用的也比較多。
    的頭像 發(fā)表于 02-25 16:21 ?771次閱讀

    嵌入式狀態(tài)機(jī)的設(shè)計(jì)與實(shí)現(xiàn)

    嵌入式狀態(tài)機(jī)是一種常用的軟件設(shè)計(jì)模式,它能夠提高代碼的可讀性和可維護(hù)性。狀態(tài)機(jī)是一個(gè)抽象的概念,它描述了一個(gè)系統(tǒng)或者組件的不同狀態(tài)以及在不同狀態(tài)
    的頭像 發(fā)表于 04-14 11:55 ?1532次閱讀

    單片機(jī)開發(fā)嵌入式開發(fā)的區(qū)別

    單片機(jī)開發(fā)嵌入式開發(fā)都是針對(duì)嵌入式系統(tǒng)的應(yīng)用領(lǐng)域,但是兩者有著不同的特點(diǎn)和應(yīng)用場(chǎng)景。在本文中,我們將探討單片機(jī)
    的頭像 發(fā)表于 04-14 16:36 ?2469次閱讀