首页> 快讯 > > 详情

[嵌入式开发模块]通用接收状态机模块 当前简讯

2023-03-27 23:19:12 来源:面包芯语

不管在哪一个状态下,如果接受缓冲区满了,都会触发flush并回到状态A。

标志字符序列

接收机定义了以下标志序列类型:

对应模块中的结构体为:


(资料图片)

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

一般的流程中,初始化接收机前,用户需要准备好接收机使用的所有标志序列,标志好每个序列的类型。模块提供宏函数以抽象这个过程:

//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

每当接收机根据标志字符序列找到一个完整或不完整的数据包时,接收机会进行回调以通知用户处理这个数据包,这个行为被称为flush,这个回调函数叫做onFlushed。

此函数的原型如下

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

整个数据包为buf指向的长度为len的区域。

数据包的状态可以通过state参数得知,RX_STATE 的类型定义如下

typedefstructRXSTATE_STRUCT{unsignedintheaderFound:1;//1:havegetheaderunsignedintenderFound:1;//1:havegetenderunsignedintisFull:1;//1:thebufferisfullunsignedintuniqueFound:1;//1:thisisuniqueflag.}RxState;

通过判断每个标志位是否置1,可以得知当前数据包的状态。如果headerFound == 1,说明数据包是有帧头的,可以通过pHorU获得帧头如果enderFound == 1,说明数据包是有帧尾的,可以通过pEnder获得帧尾如果isFull == 1,说明此数据包是因为接收区满了放不下了而产生的回调,在一些需要根据某个字段来判断数据包真正大小的协议里,可以通过调整接收缓冲区的大小来恰当的产生flush。如果UniqueFound == 1,说明此数据包是标志序列,这时缓冲区内的内容等于pHorU指向的那个标志序列

接收机类

V1.0版本中要求用户自己分配结构体的空间,为了更加面向对象,现已改为动态分配,而把具体结构体和对应方法封装在模块内部。

typedefstructRXMAC_STRUCT*RxMac;

模块提供Create函数来创建接收机实例并返回指向实例的指针。

//tocreateaninstanceofRxMac//flags标志字符串结构体的数组//flagsCnt标志字符串结构体的个数//buf用户提供给接收机用的缓冲区//bufLen缓冲区的大小(起码应该要能放的下最长的标志字符串)//onFeeded在每次被Feed时触发//onGetHeader获得头标志位时触发。//onFlushed收到一帧数据时的回调函数RxMacRxMac_Create(RXFLAG_STRUCTconstflags[],uint8_tflagsCnt,RxMacPtrbuf,uint16_tbufLen,RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed);

调用实例的方法时把这个指针作为第一个参数以模拟面向对象操作。

过滤器

接收机每次被feed时,都会触发onFeeded事件(可以在配置中取消这个事件以节省点代码)。原型如下:

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

pCurChar :指向接收区中刚收到的字符bytesCnt :这个字符是接收区中的第几个字符

此时,接收机已经将其放入接收区但是还没进一步进行判断,用户可以修改字符/配置接收机以改变接收机的行为,比如将收到的字母全变为小写。或者根据收到的数据来决定还要收多少数据。

onGetHeader事件

当找到任意帧头时会触发。

接收机运行逻辑

接收机的运作逻辑如下:

img

边际条件

标志序列尽量不要有重合,如果同时可能匹配两个标志序列,最终行为是未定义的,不保证正确执行,最终结果可能与标志序列的位置以及类型有关系。

同一个标志串可以同时是多种类型,比如同时是帧头与帧尾,但要小心类型间不要有冲突,否则不保证正确执行。

对于标志序列匹配到一半发生了接收缓冲区满,从而导致发生标志序列匹配时,接收缓冲区中只有半个标志序列的情况:如果标志序列是(强)特殊序列或(强)帧头的情况,可以保证功能正常运行。如果标志序列是强帧尾的情况,缓冲区内会只剩下后半段的帧尾,但可以根据pEnder参数来得知真正的帧尾。帧尾不会发生这种边际条件。

相关代码

此模块使用了我自己写的Buffer模块作为内部缓冲区来判断标志字符串。[嵌入式开发模块]环形缓冲区/循环队列 C语言实现

接收机代码

RxMac.h

/***********************************************************************************************UniversalReceiveStateMachine*通用接收状态机**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[]="\r\n";*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#endiftypedefuint8_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//receiveflagtypedefstructRXFLAG_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:havegetheaderunsignedintenderFound:1;//1:havegetenderunsignedintisFull:1;//1:thebufferisfullunsignedintuniqueFound: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标志字符串结构体的数组//flagsCnt标志字符串结构体的个数//buf用户提供给接收机用的缓冲区//bufLen缓冲区的大小(起码应该要能放的下最长的标志字符串)//onFeeded在每次被Feed时触发//onGetHeader获得头标志位时触发。//onFlushed收到一帧数据时的回调函数RxMacRxMac_Create(RXFLAG_STRUCTconstflags[],uint8_tflagsCnt,RxMacPtrbuf,uint16_tbufLen,RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed);//todestroytheRxMacvoidRxMac_Destroy(RxMacmac);//向接收机内喂字节voidRxMac_FeedDatas(RxMacmac,uint8_tconst*buf,uint16_tlen);voidRxMac_FeedData(RxMacmac,uint8_tc);//重置接收区长度为最长那个长度//uint8_tRxMac_ResetRxSize(RxMacmac);//设置最大接收到多少个字节uint8_tRxMac_SetRxSize(RxMacmac,uint16_tsize);//重置接收机的状态uint8_tRxMac_ResetState(RxMacmac);//强制接收机flushuint8_tRxMac_Flush(RxMacmac);//设置onFeededuint8_tRxMac_SetOnFeeded(RxMacmac,RXMAC_FILTERonFeeded);//设置onGetHeaderuint8_tRxMac_SetOnGetHeader(RxMacmac,RXMAC_FLAG_EVENTonGetHeader);//设置onFlusheduint8_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********************************************************************************************///打印内部缓冲区,返回缓冲区的长度uint16_t_RxMac_printBuffer(RxMacmac,uint8_t*buf);/*********************************************************************************************RECEIVEFLAGSTRUCT********************************************************************************************///structofRXFLAG_STRUCT.option/*typedefstructRXFLAG_OPTION{unsignedintisHeader:1;//1:theflagistheheadoftheframeunsignedintstrong_H:1;//1:strong-header,RxMacwillunsignedintnotfill_H:1;//0:filltheflagintothebufferwhenfoundasheaderunsignedintisEnder:1;//1:theflagistheendoftheframeunsignedintstrong_E:1;//unsignedintnotfill_E:1;//0:filltheflagintothebufferwhenfoundasenderunsignedintisUnique: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*通用接收状态机**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;//lengthoftheinternalbufferuint16_tRxBufSize;//Countofthebytesintheinternalbuffer/theindexfornextfeededbyteuint16_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))#elsestaticRXMAC_STRUCT_mac;//单例模式中,这个指针用于标识是否单例已初始化过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#ifdefCODEWARRIORstaticRxMacPtr_memcpy_internal(RxMacPtrdest,RxMacPtrsrc,size_tn);#definememcpy(dest,src,n)_memcpy_internal(dest,src,n)#endif#endif//冲刷缓冲区staticvoid_flush(RxMacmac,RxFlagender);//往接收机缓冲区内放数据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.创建一个接收机实例**Arguments:flagspointertotheflags(anarray);指向标志串(数组)的指针*flagsCntthecountoftheflags;有多少个标志串;*bufpointertothebufferprovidedtotheRxMac;提供给接收机使用的缓存*bufLenthesizeofthebuffer.缓存的大小*onFeededthecallbackfuncthatwillbecalledeverytimefeeded,you*canmodifythefeededbyteinthiscallback.*每次被feed时会调用的回调函数,如改变对应数据值会影响标志位的判断*onGetHeaderthecallbackfuncthatwillbecalledwhenfindaheader.*当发现帧头时会调用的回调函数*onFlushedthecallbackfuncthatwillbecalledwhenflushed.*当Flush时会调用的回调函数**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_ENRxMacmac;#endif#ifndefRXMAC_ARGUMENT_CHECK_DISABLEif((flags==NULL&&flagsCnt>0)||buf==NULL)returnNULL;#endif//findoutthemaxlengthofflags.for(i=0;imaxLen)maxLen=flags[i].len;}#ifndefRXMAC_ARGUMENT_CHECK_DISABLEif(bufLen0)*p++=*src++;returndest;}staticvoid_BufIn(RxMacmac,RxMacPtrbuf,uint16_tlen){memcpy(_pRxBuf+_RxCnt,buf,len);_RxCnt+=len;}staticvoid_flush(RxMacmac,RxFlagender){//触发回调if((_RxCnt>0||ender!=NULL)&&_fonFlushed!=NULL)_fonFlushed(_pMac,_pRxBuf,_RxCnt,_state,_pHorU,ender);//复位接收机_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_DISABLEif(!_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_DISABLEif(_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);//masktoidentifypossibleflagmask=(_state.headerFound)?STATEMASK_STEPB:STATEMASK_STEPA;for(i=0;i<_FlagsCnt;i++){if((_Flags[i].option&mask)&&BufferUINT8Indexed_BackMatch(_BufForFlag,_Flags[i].pBuf,_Flags[i].len)){Buffer_Cleanup((Buffer)_BufForFlag);return&_Flags[i];}}returnNULL;}staticBOOL_RxFlagMgr_Init(RxMacmac,RxFlagflags,uint8_tflagsCnt,uint8_tmaxLen){if(_BufForFlag=(BufferIndexed)BufferUINT8MallocArray_Create(maxLen)){_Flags=flags;_FlagsCnt=flagsCnt;_stateByte=0;}return_BufForFlag!=NULL;}staticvoid_RxFlagMgr_Destroy(RxMacmac){Buffer_Destroy(_BufForFlag);}staticvoid_RxFlagMgr_Reset(RxMacmac){Buffer_Cleanup((Buffer)_BufForFlag);}

测试/示例代码

已略去非必要代码

#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_SIZE20staticuint8_tbuffer[BUF_SIZE];//协议示例1://帧头:HEADER或者START//强帧尾:END//强特殊串: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);}//协议示例2://帧头:START//帧头后的第1个字符表示后面还要接收多少个字符1-9,"4"表示4个,如果不是数字或为"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){//因为发现帧头后才挂载事件,所以下一次回掉正好是说明字符数的那个字符,否则还得根据bytesCnt来判断当前位置RxMac_SetOnFeeded(sender,NULL);if(*pCurChar>"0"&&*pCurChar<="9"){//bytesCnt是当前收到了多少个字符,所以接收区大小为当前字符数加上还要接收的RxMac_SetRxSize(sender,*pCurChar-"0"+bytesCnt);}}staticvoidonFlushed(RxMacsender,RxMacPtrbuf,uint16_tlen,RxStatestate,RxFlagHorU,RxFlagEnder){buf[len]="\0";printf("\nFlushed:");if(state.headerFound)printf("headerFound,");if(state.enderFound)printf("enderFound,");if(state.isFull)printf("full,");if(state.uniqueFound)printf("unique,");printf("\nDatas:%s\n",buf);RxMac_SetRxSize(sender,BUF_SIZE);}staticvoidonGetHeader(RxMacsender,RxFlagflag){printf("\nFoundHeader:%s\n",flag->pBuf);}staticvoidonGetHeader2(RxMacsender,RxFlagflag){printf("\nFoundHeader:%s\n",flag->pBuf);RxMac_SetOnFeeded(sender,onGetData);}/***********************************************************************************************************MAINFUNCTION**********************************************************************************************************/voidmain(void){//选择想要实验的协议来初始化protocol1_init();//protocol2_init();while(1){c=getchar();//回显putchar(c);RxMac_FeedData(mac,c);}}

示例协议1测试结果

示例协议2测试结果可以看到,第二个协议中我们通过改变缓冲区大小成功控制了数据包的长度。

虽然这里的示例都是基于ASCII的,但这只是为了观察起来方便,普通的基于二进制的协议也是可以使用这个模块的。

v1.0代码

旧版代码中引用了我自己写的(现已弃用)环形缓冲区模块:https://blog.csdn.net/lin_strong/article/details/73604561

接收机代码

头文件

/*************************************************************************************************************UniversalReceiveStateMachine*通用接收状态机**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[]="\r\n";*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_MODEtypedefINT8URB_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:theflagistheheadoftheframeunsignedintstrong_H:1;//1:strong-header,RxMacwillunsignedintnotfill_H:1;//0:filltheflagintothebufferwhenfoundasheaderunsignedintisEnder:1;//1:theflagistheendoftheframeunsignedintstrong_E:1;//unsignedintnotfill_E:1;//0:filltheflagintothebufferwhenfoundasenderunsignedintisUnique:1;//1:theflagisauniqueflagwhichistreatedassingleframe.unsignedintstrong_U:1;//0:whenreceivingaframe,RxMacwillnot};//*///接收标志位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_UNIQUE0xC0typedefstructrx_state{unsignedintheaderFound:1;//1:havegetheaderunsignedintenderFound:1;//1:havegetenderunsignedintisFull:1;//1:thebufferisfullunsignedintuniqueFound: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;//用于判断标志串的环形缓冲区对象pRX_FLAGFlags;//标志数组INT8UFlagsCnt;//标志数组的个数RX_STATEstate;//接收的状态(内部使用)pRX_FLAGpHorU;//内部使用pRB_BYTEpRxBuf;//存放数据的缓冲区INT16URxBufSize;//缓冲区的长度pRB_BYTEpCur;//指向缓冲区内下一个填充字符的位置RXMAC_FILTERonFeeded;//当被喂字符时触发,返回指向缓冲区中刚刚喂进来的字符的指针以及是缓冲区内的第几个字符RXMAC_FLAG_EVENTonGetHeader;//获得头标志位时触发。RXMAC_FLUSH_EVENTonFlushed;//回调函数};/***********************************************************************************************************FUNCTIONDECLARATION**********************************************************************************************************///tosettheflag"soption//pbufpointertotheflagbuffer//bufSizesizeofflag//optseeFLAG_OPTION_XXXXX#defineRX_FLAG_INIT(pFlag,pbuf,bufSize,opt)\(pFlag)->pBuf=(pbuf);(pFlag)->len=(bufSize);(pFlag)->option=(opt);//toinittheRxMacINT8URxMac_Init(pRX_MACpRxMac,//需要用户自己申请个UNI_RX_MACHINE对象的空间RX_FLAGFlags[],INT8UFlagsCnt,INT8UmaxLenOfFlags,//提供标志字符串的数组pRB_BYTEpBuf,INT16UBufLen,//用户需要提供缓冲区(缓存区大小起码应该要能//放的下最长的Flag+最长的帧,最后部分会分配给RQ)RXMAC_FILTERonFeeded,//在每次被Feed时触发RXMAC_FLAG_EVENTonGetHeader,//获得头标志位时触发。RXMAC_FLUSH_EVENTonFlushed//收到一帧数据时的回调函数);//向接收机内喂字节voidRxMac_FeedData(pRX_MACpRxMac,INT8Uc);//重置接收区长度为最长那个长度INT8URxMac_ResetRxSize(pRX_MACpRxMac);//设置最大接收到多少个字节INT8URxMac_SetRxSize(pRX_MACpRxMac,INT16Usize);//重置接收机的状态INT8URxMac_ResetState(pRX_MACpRxMac);//强制接收机flushINT8URxMac_Flush(pRX_MACpRxMac);//设置onFeededINT8URxMac_SetOnFeeded(pRX_MACpRxMac,RXMAC_FILTERonFeeded);//设置onGetHeaderINT8URxMac_SetOnGetHeader(pRX_MACpRxMac,RXMAC_FLAG_EVENTonGetHeader);//设置onFlushedINT8URxMac_SetOnFlushed(pRX_MACpRxMac,RXMAC_FLUSH_EVENTonFlushed);#endif//ofRX_MAC_H

源文件:

/*************************************************************************************************************UniversalReceiveStateMachine*通用接收状态机**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#elsestaticRX_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)//因为不能保证用户把数据放在非分页区,只好自己实现一个,实际使用中如果确定在非分页区可以把下面的宏替换为库函数memcpystaticpRB_BYTE_memcpy_internal(pRB_BYTEdest,pRB_BYTEsrc,size_tn);#define_memcpy(dest,src,n)_memcpy_internal(dest,src,n)//冲刷缓冲区staticvoid_flush(pRX_MACpRxMac,pRX_FLAGender);//往接收机缓冲区内放数据staticvoid_BufIn(pRX_MACpRxMac,pRB_BYTEpBuf,INT16Ulen);/***********************************************************************************************************RxMac_Init()**Description:ToinitializeaRxMac.初始化接收机**Arguments:pRxMacpointertotheRxMacstruct;指向接收机结构体的指针*Flagspointertotheflags(anarray);指向标志串(数组)的指针*FlagsCntthecountoftheflags;有多少个标志串;*maxLenOfFlagsthemaxlengthofflags;标志字符串最长的长度*pBufpointertothebufferprovidedtotheRxMac;提供给接收机使用的缓存*BufLenthesizeofthebuffer.缓存的大小*onFeededthecallbackfuncthatwillbecalledwhenfeeded.*每次被feed时会调用的回调函数,如改变对应数据值会影响标志位的判断*onGetHeaderthecallbackfuncthatwillbecalledwhenfindaheader.*当发现帧头时会调用的回调函数*onFlushedthecallbackfuncthatwillbecalledwhenflushed.*当Flush时会调用的回调函数**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||#endifFlags==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;#endifBufLen-=maxLenOfFlags;//把buffer的最后一段分配给环形缓冲区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.用于给接收机下一个字符**Arguments:pRxMacpointertotheRxMacstruct;指向接收机结构体的指针*cthechartofeed;下一个字符**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;//填入缓冲区#if(RXMAC_ONFEEDED_EN)if(_onFeeded!=NULL)_onFeeded(_pRxMac,pCurChar,_pCur-_pRxBuf);RingQueueIn(&_FlagQueue,*pCurChar,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&i);#elseRingQueueIn(&_FlagQueue,c,RQ_OPTION_WHEN_FULL_DISCARD_FIRST,&i);#endif//_state.headerFound==1说明在等待帧尾,否则在等待帧头mask=(_state.headerFound)?STATEMASK_STEPB:STATEMASK_STEPA;//寻找匹配的标志串for(i=0;i<_FlagsCnt;i++){if((_Flags[i].option&mask)&&(RingQueueMatch(&_FlagQueue,(pRQTYPE)_Flags[i].pBuf,_Flags[i].len)>=0)){RingQueueClear(&_FlagQueue);pFlag=&_Flags[i];break;}}//如果没有发现标志串,检查下有没满了,满了就Flushif(pFlag==NULL){if(_isRxBufFull()){_state.isFull=1;_flush(_pRxMac,NULL);}return;}//这4种标志串要_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.重置接收缓冲区**Arguments:pRxMacpointertotheRxMacstruct;指向接收机结构体的指针**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;#endifsize=_FlagQueue.RingBuf-_pRxBuf;#if(RXMAC_ARGUMENT_CHECK_EN)if(size<0)returnRXMAC_ERR_INIT;#endif_RxBufSize=(INT16U)size;returnRXMAC_ERR_NONE;}/***********************************************************************************************************RxMac_SetRxSize()**Description:setthesizeofRxBuftothemaxsize.重置接收缓冲区**Arguments:pRxMacpointertotheRxMacstruct;指向接收机结构体的指针*sizethesizetoset;**Return:RXMAC_ERR_NONEifSuccess;*RXMAC_ERR_POINTERNULLifpRxMac==NULL*RXMAC_ERR_ARGUMENTifsizeiswrong.*Note(s):thesizeshouldn"tbebiggerthantheinitialvalue,andshouldbiggerthan*thecurrentnumberofcharsintheRxBuf.***********************************************************************************************************/INT8URxMac_SetRxSize(pRX_MACpRxMac,INT16Usize){#if(RXMAC_ARGUMENT_CHECK_EN)#if(!RXMAC_SINGLETON_EN)if(_pRxMac==NULL)returnRXMAC_ERR_POINTERNULL;#endifif(_FlagQueue.RingBuf-_pRxBuf0)*p++=*src++;returndest;}staticvoid_BufIn(pRX_MACpRxMac,pRB_BYTEpBuf,INT16Ulen){_memcpy(_pCur,pBuf,len);_pCur+=len;}staticvoid_flush(pRX_MACpRxMac,pRX_FLAGender){//触发回调if(_pCur-_pRxBuf>0&&_onFlushed!=NULL)_onFlushed(_pRxMac,_pRxBuf,_pCur-_pRxBuf,_state,_pHorU,ender);//复位接收机_pCur=_pRxBuf;_stateByte=0;_pHorU=NULL;}

测试/示例代码

/***********************************************************************************************************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){//因为发现帧头后才挂载事件,所以下一次回掉正好是说明字符数的那个字符,否则还得根据bytesCnt来判断当前位置RxMac_SetOnFeeded(sender,NULL);if(*pCurChar>"0"&&*pCurChar<="9"){//bytesCnt是当前收到了多少个字符,所以接收区大小为当前字符数加上还要接收的RxMac_SetRxSize(sender,*pCurChar-"0"+bytesCnt);}}voidonFlushed(pRX_MACsender,pRB_BYTEpBuf,INT16Ulen,RX_STATEstate,pRX_FLAGpHorU,pRX_FLAGpEnder){SCI_PutCharsB(SCI0,"\nFlushed:",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,"\nDatas:",7,0);SCI_PutCharsB(SCI0,pBuf,len,0);SCI_PutCharsB(SCI0,"\n",1,0);RxMac_ResetRxSize(sender);}voidonGetHeader(pRX_MACsender,pRX_FLAGpFlag){SCI_PutCharsB(SCI0,"\nFoundHeader:",13,0);SCI_PutCharsB(SCI0,pFlag->pBuf,pFlag->len,0);SCI_PutCharsB(SCI0,"\n",1,0);}voidonGetHeader2(pRX_MACsender,pRX_FLAGpFlag){SCI_PutCharsB(SCI0,"\nFoundHeader:",13,0);SCI_PutCharsB(SCI0,pFlag->pBuf,pFlag->len,0);SCI_PutCharsB(SCI0,"\n",1,0);RxMac_SetOnFeeded(sender,onGetData);}/***********************************************************************************************************FLAGS**********************************************************************************************************/RX_MAC_rxmac;#defineBUF_SIZE20INT8Ubuffer[BUF_SIZE];RX_FLAGflags[4];//协议示例1://帧头:HEADER或者START//强帧尾:END//强特殊串: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);}//协议示例2://帧头:START//帧头后的第1个字符表示后面还要接收多少个字符1-9,"4"表示4个,如果不是数字或为"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();//选择想要实验的协议来初始化protocol1_init();//protocol2_init();while(DEF_TRUE){//获取下一个字符c=SCI_GetCharB(SCI0,0,&err);//回显SCI_PutCharB(SCI0,c,0);//喂给接收机RxMac_FeedData(&_rxmac,c);}}

关键词:

上一篇:今日视点:广播剧《默读》1~5季资源|骆闻舟费渡
下一篇:最后一页