前言
在软件开发的过程中,只要涉及到通信,就会涉及到数据接收机的编写,通信协议虽然多种多样,但是数据包的形式确是很相似的(暂时没看到特别复杂,此模块解决不了的),为此可以把其中通用的部分抽象出来,然后就成了这个模块。
模块相关概念和逻辑
接收机状态
接收机有两个基本状态:
状态A:preRx 等待帧头中,这个时候接收机会不断判断是否收到了特殊序列、帧头和强帧尾。如果收到了帧头,则(默认)会把帧头填入缓冲区的最前面,然后进入状态B。
状态B:Rxing 等待帧尾中,收到的数据会按序填入接收缓冲区,同时不断查找帧尾、强帧头以及强特殊序列,不管找到了哪一个都会触发flush。如果,找到的是强帧头,则仍然在状态B,否则恢复状态A。
不管在哪一个状态下,如果接受缓冲区满了,都会触发flush并回到状态A。
标志字符序列
接收机定义了以下标志序列类型:
类型 | 模块中标记 | 描述 |
---|---|---|
帧头 | header | 只在状态A起作用;找到时会导致之前接收区内的数据被flush,然后默认会填入接收区的最前面,可以通过选项来改变这个行为,然后接收机进入状态B。 |
强帧头 | strong-header | 在状态B也会起作用,其他行为与普通帧头一样 |
帧尾 | ender | 只在状态B起作用;找到时会导致当前接收区内的数据被flush,默认会处于回调时给用户的buffer的最后面,可以通过选项来改变这个行为,然后接收机回到状态A。 |
强帧头 | strong-header | 在状态A也会起作用,其他行为与普通帧尾一样 |
特殊序列 | unique | 只在状态A起作用;找到时会导致之前接收区内的数据被flush,然后自己被填入接收区内后再次触发flush,然后接收机回到状态A。 |
强特殊序列 | strong-unique | 在状态B也会起作用,其他行为与特殊序列一样 |
对应模块中的结构体为:
//receiveflag typedefstructRXFLAG_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:havegetheader unsignedintenderFound:1;//1:havegetender unsignedintisFull:1;//1:thebufferisfull unsignedintuniqueFound: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[]=" "; *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标志字符串结构体的数组 //flagsCnt标志字符串结构体的个数 //buf用户提供给接收机用的缓冲区 //bufLen缓冲区的大小(起码应该要能放的下最长的标志字符串) //onFeeded在每次被Feed时触发 //onGetHeader获得头标志位时触发。 //onFlushed收到一帧数据时的回调函数 RxMacRxMac_Create(RXFLAG_STRUCTconstflags[],uint8_tflagsCnt,RxMacPtrbuf,uint16_tbufLen,RXMAC_FILTERonFeeded,RXMAC_FLAG_EVENTonGetHeader,RXMAC_FLUSH_EVENTonFlushed); //todestroytheRxMac voidRxMac_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); //强制接收机flush uint8_tRxMac_Flush(RxMacmac); //设置onFeeded uint8_tRxMac_SetOnFeeded(RxMacmac,RXMAC_FILTERonFeeded); //设置onGetHeader uint8_tRxMac_SetOnGetHeader(RxMacmac,RXMAC_FLAG_EVENTonGetHeader); //设置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 ******************************************************************************************* */ //打印内部缓冲区,返回缓冲区的长度 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 *通用接收状态机 * *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; //单例模式中,这个指针用于标识是否单例已初始化过 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 //冲刷缓冲区 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_EN RxMacmac; #endif #ifndefRXMAC_ARGUMENT_CHECK_DISABLE if((flags==NULL&&flagsCnt>0)||buf==NULL) returnNULL; #endif //findoutthemaxlengthofflags. for(i=0;i< flagsCnt; i++){ if(flags[i].len >maxLen) maxLen=flags[i].len; } #ifndefRXMAC_ARGUMENT_CHECK_DISABLE if(bufLen< maxLen){ return NULL; } #endif #ifdef RXMAC_SINGLETON_EN if(_pMac != NULL) // if have created one instance, free the previous FlagBuf _RxFlagMgr_Destroy(&_mac); else _pMac = &_mac; #else if((mac = (RxMac)malloc(sizeof(RXMAC_STRUCT))) == NULL){ return NULL; } #endif if(!_RxFlagMgr_Init(_pMac,flags,flagsCnt,maxLen)){ _RxMac_Destroy(); return NULL; } _pHorU = NULL; _pRxBuf = buf; _RxCnt = 0; _RxBufSize = bufLen; _fonFeeded = onFeeded; _fonGetHeader = onGetHeader; _fonFlushed = onFlushed; return _pMac; } /* ******************************************************************************************* * RxMac_Destroy() * * Description : Destroy a receive machine instance. * * Arguments : mac the target receive machine. 目标接收机 * * Return : * * Note(s) : * ******************************************************************************************* */ void RxMac_Destroy(RxMac mac){ if(_pMac == NULL) return; _RxFlagMgr_Destroy(mac); _RxMac_Destroy(); } /* ******************************************************************************************* * RxMac_FeedData(s) * * Description : To feed RxMac the next char(s). 用于给接收机下一个字符 * * Arguments : mac the target receive machine. 目标接收机 * c the char to feed; 下一个字符 * * Return : * * Note(s) : ******************************************************************************************* */ void RxMac_FeedDatas(RxMac mac, uint8_t const * buf, uint16_t len){ uint16_t i; for(i = 0; i < len; i++) RxMac_FeedData(mac,buf[i]); } void RxMac_FeedData(RxMac mac,uint8_t c){ RxFlag curFlag; _checkMacNotNull_void(); _onFeeded(&c,_RxCnt + 1); _pRxBuf[_RxCnt++] = c; curFlag = _RxFlagMgr_GetNextMatchedAtThisState(mac,c); if(curFlag == NULL){ // if no flag match _RxMac_FlushIfFull(mac); return; } _RxMac_RecordAndFlushPreBytesIfGotHeaderOrUnique(mac,curFlag); if(_RxFlag_isHeader(curFlag)){ _RxMac_GetHeaderProcess(mac,curFlag); }else if(_RxFlag_isUnique(curFlag)){ _RxMac_GetUniqueProcess(mac,curFlag); }else{ // if(_RxFlag_isEnder(curFlag)) _RxMac_GetEnderProcess(mac,curFlag); } } /* ******************************************************************************************* * RxMac_SetRxSize() * * Description : set the size of RxBuf. 设置接收缓冲区的大小 * * Arguments : mac the target receive machine. 目标接收机 * size the size to set; * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if mac == NULL * RXMAC_ERR_ARGUMENT if size is wrong. * Note(s) : the size should bigger than the current number of chars in the RxBuf. * ******************************************************************************************* */ uint8_t RxMac_SetRxSize(RxMac mac, uint16_t size){ _checkMacNotNull(); #ifndef RXMAC_ARGUMENT_CHECK_DISABLE if(size <= _RxCnt) return RXMAC_ERR_ARGUMENT; #endif _RxBufSize = size; return RXMAC_ERR_NONE; } /* ******************************************************************************************* * RxMac_ResetState() * * Description : reset the state of receive machine. 重置接收机的状态 * * Arguments : mac the target receive machine. 目标接收机 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if mac == NULL * Note(s) : it will not trigger call-back of onFlush. ******************************************************************************************* */ uint8_t RxMac_ResetState(RxMac mac){ _checkMacNotNull(); // 复位接收机 Buffer_Cleanup((Buffer)_BufForFlag); _RxCnt = 0; _stateByte = 0; _pHorU = NULL; return RXMAC_ERR_NONE; } /* ******************************************************************************************* * RxMac_Flush() * * Description : force receive machine to flush. * * Arguments : mac the target receive machine. 目标接收机 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if mac == NULL * * Note(s) : it will force receive machine to flush, if there is any data in the RxBuffer, * ******************************************************************************************* */ uint8_t RxMac_Flush(RxMac mac){ _checkMacNotNull(); _flush(_pMac,NULL); return RXMAC_ERR_NONE; } /* ****************************************************************************************** * RxMac_SetOnFeeded() * * Description : set the onFeeded callback function. * * Arguments : mac the target receive machine. 目标接收机 * onFeeded the callback function to set; 要设置的回调函数 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if mac == NULL * * Note(s) : * ****************************************************************************************** */ uint8_t RxMac_SetOnFeeded(RxMac mac,RXMAC_FILTER onFeeded){ _checkMacNotNull(); _fonFeeded = onFeeded; return RXMAC_ERR_NONE; } /* ****************************************************************************************** * RxMac_SetOnGetHeader() * * Description : set the onGetHeader callback function. * * Arguments : mac the target receive machine. 目标接收机 * onGetHeader the callback function to set; 要设置的回调函数 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if mac == NULL * * Note(s) : * ****************************************************************************************** */ uint8_t RxMac_SetOnGetHeader(RxMac mac,RXMAC_FLAG_EVENT onGetHeader){ _checkMacNotNull(); _fonGetHeader = onGetHeader; return RXMAC_ERR_NONE; } /* ****************************************************************************************** * RxMac_SetOnFlushed() * * Description : set the onFlushed callback function. * * Arguments : mac the target receive machine. 目标接收机 * onFlushed the callback function to set; 要设置的回调函数 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * * Note(s) : * ****************************************************************************************** */ uint8_t RxMac_SetOnFlushed(RxMac mac,RXMAC_FLUSH_EVENT onFlushed){ _checkMacNotNull(); _fonFlushed = onFlushed; return RXMAC_ERR_NONE; } /* ****************************************************************************************** * _RxMac_printBuffer() * * Description : print the internal buffer, just for developer. * 给开发者用于查看内部缓存的 * * Arguments : mac the target receive machine. 目标接收机 * onFlushed the callback function to set; 要设置的回调函数 * * Return : the len of buffer printed. * * Note(s) : * ****************************************************************************************** */ uint16_t _RxMac_printBuffer(RxMac mac,uint8_t * buf){ memcpy(buf,_pRxBuf,_RxCnt); return _RxCnt; } /* ****************************************************************************************** * LOCAL FUNCITON ****************************************************************************************** */ static RxMacPtr _memcpy_internal(RxMacPtr dest, RxMacPtr src, size_t n){ RxMacPtr p = dest; while(n-- >0) *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_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(_RxCnt< flagJustGot->len){//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< _FlagsCnt; i++){ if((_Flags[i].option & mask) && BufferUINT8Indexed_BackMatch(_BufForFlag,_Flags[i].pBuf,_Flags[i].len)){ Buffer_Cleanup((Buffer)_BufForFlag); return &_Flags[i]; } } return NULL; } static BOOL _RxFlagMgr_Init(RxMac mac,RxFlag flags,uint8_t flagsCnt,uint8_t maxLen){ if(_BufForFlag = (BufferIndexed)BufferUINT8MallocArray_Create(maxLen)){ _Flags = flags; _FlagsCnt = flagsCnt; _stateByte = 0; } return _BufForFlag != NULL; } static void _RxFlagMgr_Destroy(RxMac mac){ Buffer_Destroy(_BufForFlag); } static void _RxFlagMgr_Reset(RxMac mac){ 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_SIZE20 staticuint8_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); } } 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){ //选择想要实验的协议来初始化 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[]=" "; *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 };//*/ //接收标志位 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;//用于判断标志串的环形缓冲区对象 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); //toinittheRxMac INT8URxMac_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); //强制接收机flush INT8URxMac_Flush(pRX_MACpRxMac); //设置onFeeded INT8URxMac_SetOnFeeded(pRX_MACpRxMac,RXMAC_FILTERonFeeded); //设置onGetHeader INT8URxMac_SetOnGetHeader(pRX_MACpRxMac,RXMAC_FLAG_EVENTonGetHeader); //设置onFlushed INT8URxMac_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 #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) //因为不能保证用户把数据放在非分页区,只好自己实现一个,实际使用中如果确定在非分页区可以把下面的宏替换为库函数memcpy staticpRB_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|| #endif Flags==NULL||pBuf==NULL) returnRXMAC_ERR_POINTERNULL; #endif //findoutthemaxlengthofflags. //for(i=0;i< FlagsCnt; i++){ // if(Flags[i].len >maxLen) //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的最后一段分配给环形缓冲区 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); #else RingQueueIn(&_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; } } //如果没有发现标志串,检查下有没满了,满了就Flush if(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; #endif size=_FlagQueue.RingBuf-_pRxBuf; #if(RXMAC_ARGUMENT_CHECK_EN) if(size< 0) return RXMAC_ERR_INIT; #endif _RxBufSize = (INT16U)size; return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * RxMac_SetRxSize() * * Description : set the size of RxBuf to the max size. 重置接收缓冲区 * * Arguments : pRxMac pointer to the RxMac struct; 指向接收机结构体的指针 * size the size to set; * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * RXMAC_ERR_ARGUMENT if size is wrong. * Note(s) : the size shouldn't be bigger than the initial value, and should bigger than * the current number of chars in the RxBuf. * ********************************************************************************************************* */ INT8U RxMac_SetRxSize(pRX_MAC pRxMac, INT16U size){ #if(RXMAC_ARGUMENT_CHECK_EN) #if (!RXMAC_SINGLETON_EN) if(_pRxMac == NULL) return RXMAC_ERR_POINTERNULL; #endif if(_FlagQueue.RingBuf - _pRxBuf < size || size <= _pCur - _pRxBuf) return RXMAC_ERR_ARGUMENT; #endif _RxBufSize = size; return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * RxMac_ResetState() * * Description : reset the state of receive machine. 重置接收机的状态 * * Arguments : pRxMac pointer to the RxMac struct; 指向接收机结构体的指针 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * Note(s) : it will not trigger call-back of onFlush. ********************************************************************************************************* */ INT8U RxMac_ResetState(pRX_MAC pRxMac){ #if(RXMAC_ARGUMENT_CHECK_EN && !RXMAC_SINGLETON_EN) if(_pRxMac == NULL) return RXMAC_ERR_POINTERNULL; #endif // 复位接收机 RingQueueClear(&_FlagQueue); _pCur = _pRxBuf; _stateByte = 0; _pHorU = NULL; return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * RxMac_Flush() * * Description : force receive machine to flush. * * Arguments : pRxMac pointer to the RxMac struct; 指向接收机结构体的指针 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * * Note(s) : it will force receive machine to flush, if there is any data in the RxBuffer, * ********************************************************************************************************* */ INT8U RxMac_Flush(pRX_MAC pRxMac){ #if(RXMAC_ARGUMENT_CHECK_EN && !RXMAC_SINGLETON_EN) if(_pRxMac == NULL) return RXMAC_ERR_POINTERNULL; #endif _flush(_pRxMac,NULL); return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * RxMac_SetOnFeeded() * * Description : set the onFeeded callback function. * * Arguments : pRxMac pointer to the RxMac struct; 指向接收机结构体的指针 * onFeeded the callback function to set; 要设置的回调函数 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * * Note(s) : * ********************************************************************************************************* */ INT8U RxMac_SetOnFeeded(pRX_MAC pRxMac,RXMAC_FILTER onFeeded){ #if(RXMAC_ARGUMENT_CHECK_EN && !RXMAC_SINGLETON_EN) if(_pRxMac == NULL) return RXMAC_ERR_POINTERNULL; #endif _onFeeded = onFeeded; return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * RxMac_SetOnGetHeader() * * Description : set the onGetHeader callback function. * * Arguments : pRxMac pointer to the RxMac struct; 指向接收机结构体的指针 * onGetHeader the callback function to set; 要设置的回调函数 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * * Note(s) : * ********************************************************************************************************* */ INT8U RxMac_SetOnGetHeader(pRX_MAC pRxMac,RXMAC_FLAG_EVENT onGetHeader){ #if(RXMAC_ARGUMENT_CHECK_EN && !RXMAC_SINGLETON_EN) if(_pRxMac == NULL) return RXMAC_ERR_POINTERNULL; #endif _onGetHeader = onGetHeader; return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * RxMac_SetOnFlushed() * * Description : set the onFlushed callback function. * * Arguments : pRxMac pointer to the RxMac struct; 指向接收机结构体的指针 * onFlushed the callback function to set; 要设置的回调函数 * * Return : RXMAC_ERR_NONE if Success; * RXMAC_ERR_POINTERNULL if pRxMac == NULL * * Note(s) : * ********************************************************************************************************* */ INT8U RxMac_SetOnFlushed(pRX_MAC pRxMac,RXMAC_FLUSH_EVENT onFlushed){ #if(RXMAC_ARGUMENT_CHECK_EN && !RXMAC_SINGLETON_EN) if(_pRxMac == NULL) return RXMAC_ERR_POINTERNULL; #endif _onFlushed = onFlushed; return RXMAC_ERR_NONE; } /* ********************************************************************************************************* * LOCAL FUNCITON ********************************************************************************************************* */ static pRB_BYTE _memcpy_internal(pRB_BYTE dest, pRB_BYTE src, size_t n){ pRB_BYTE p = dest; while(n-- >0) *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); } } 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]; //协议示例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); } }
审核编辑:汤梓红
-
模块
+关注
关注
7文章
2668浏览量
47332 -
嵌入式
+关注
关注
5068文章
19008浏览量
303017 -
接收机
+关注
关注
8文章
1179浏览量
53406 -
函数
+关注
关注
3文章
4304浏览量
62412 -
状态机
+关注
关注
2文章
492浏览量
27470
原文标题:[嵌入式开发模块]通用接收状态机模块
文章出处:【微信号:技术让梦想更伟大,微信公众号:技术让梦想更伟大】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论