Zorb Framework是一個(gè)基于面向?qū)ο蟮乃枷雭?lái)搭建一個(gè)輕量級(jí)的嵌入式框架。
本次分享的是Zorb Framework的狀態(tài)機(jī)的實(shí)現(xiàn)。
中小型嵌入式程序說(shuō)白了就是由各種狀態(tài)機(jī)組成,因此掌握了如何構(gòu)建狀態(tài)機(jī),開發(fā)嵌入式應(yīng)用程序可以說(shuō)是手到拈來(lái)。
簡(jiǎn)單的狀態(tài)機(jī)可以用Switch-Case實(shí)現(xiàn),但復(fù)雜一點(diǎn)的狀態(tài)機(jī)再繼續(xù)使用Switch-Case的話,層次會(huì)變得比較亂,不方便維護(hù)。因此我們?yōu)閆orb Framework提供了函數(shù)式狀態(tài)機(jī)。
狀態(tài)機(jī)的功能
我們先來(lái)看看要實(shí)現(xiàn)的狀態(tài)機(jī)提供什么功能:
初步要提供的功能如下:
1、可以設(shè)置初始狀態(tài)
2、可以進(jìn)行狀態(tài)轉(zhuǎn)換
3、可以進(jìn)行信號(hào)調(diào)度
4、最好可以在進(jìn)入和離開狀態(tài)的時(shí)候可以做一些自定義的事情
5、最好可以有子狀態(tài)機(jī)
因此,初步設(shè)計(jì)的數(shù)據(jù)結(jié)構(gòu)如下:
/*狀態(tài)機(jī)結(jié)構(gòu)*/ struct_Fsm { uint8_tLevel;/*嵌套層數(shù),根狀態(tài)機(jī)層數(shù)為1,子狀態(tài)機(jī)層數(shù)自增*/ /*注:嚴(yán)禁遞歸嵌套和環(huán)形嵌套*/ List*ChildList;/*子狀態(tài)機(jī)列表*/ Fsm*Owner;/*父狀態(tài)機(jī)*/ IFsmStateOwnerTriggerState;/*當(dāng)父狀態(tài)機(jī)為設(shè)定狀態(tài)時(shí),才觸發(fā)當(dāng)前狀態(tài)機(jī)*/ /*若不設(shè)定,則當(dāng)執(zhí)行完父狀態(tài)機(jī),立即運(yùn)行子狀態(tài)機(jī)*/ IFsmStateCurrentState;/*當(dāng)前狀態(tài)*/ boolIsRunning;/*是否正在運(yùn)行(默認(rèn)關(guān))*/ /*設(shè)置初始狀態(tài)*/ void(*SetInitialState)(Fsm*constpFsm,IFsmStateinitialState); /*運(yùn)行當(dāng)前狀態(tài)機(jī)*/ bool(*Run)(Fsm*constpFsm); /*運(yùn)行當(dāng)前狀態(tài)機(jī)和子狀態(tài)機(jī)*/ bool(*RunAll)(Fsm*constpFsm); /*停止當(dāng)前狀態(tài)機(jī)*/ bool(*Stop)(Fsm*constpFsm); /*停止當(dāng)前狀態(tài)機(jī)和子狀態(tài)機(jī)*/ bool(*StopAll)(Fsm*constpFsm); /*釋放當(dāng)前狀態(tài)機(jī)*/ bool(*Dispose)(Fsm*constpFsm); /*釋放當(dāng)前狀態(tài)機(jī)和子狀態(tài)機(jī)*/ bool(*DisposeAll)(Fsm*constpFsm); /*添加子狀態(tài)機(jī)*/ bool(*AddChild)(Fsm*constpFsm,Fsm*constpChildFsm); /*移除子狀態(tài)機(jī)(不釋放空間)*/ bool(*RemoveChild)(Fsm*constpFsm,Fsm*constpChildFsm); /*調(diào)度狀態(tài)機(jī)*/ bool(*Dispatch)(Fsm*constpFsm,FsmSignalconstsignal); /*狀態(tài)轉(zhuǎn)移*/ void(*Transfer)(Fsm*constpFsm,IFsmStatenextState); /*狀態(tài)轉(zhuǎn)移(觸發(fā)轉(zhuǎn)出和轉(zhuǎn)入事件)*/ void(*TransferWithEvent)(Fsm*constpFsm,IFsmStatenextState); };
關(guān)于信號(hào),Zorb Framework做了以下定義:
/*狀態(tài)機(jī)信號(hào)0-31保留,用戶信號(hào)在32以后定義*/ enum{ FSM_NULL_SIG=0, FSM_ENTER_SIG, FSM_EXIT_SIG, FSM_USER_SIG_START=32 /*用戶信號(hào)請(qǐng)?jiān)谟脩粑募x,不允許在此定義*/ };
創(chuàng)建狀態(tài)機(jī):
boolFsm_create(Fsm**ppFsm) { Fsm*pFsm; ZF_ASSERT(ppFsm!=(Fsm**)0) /*分配空間*/ pFsm=ZF_MALLOC(sizeof(Fsm)); if(pFsm==NULL) { ZF_DEBUG(LOG_E,"mallocfsmspaceerror "); returnfalse; } /*初始化成員*/ pFsm->Level=1; pFsm->ChildList=NULL; pFsm->Owner=NULL; pFsm->OwnerTriggerState=NULL; pFsm->CurrentState=NULL; pFsm->IsRunning=false; /*初始化方法*/ pFsm->SetInitialState=Fsm_setInitialState; pFsm->Run=Fsm_run; pFsm->RunAll=Fsm_runAll; pFsm->Stop=Fsm_stop; pFsm->StopAll=Fsm_stopAll; pFsm->Dispose=Fsm_dispose; pFsm->DisposeAll=Fsm_disposeAll; pFsm->AddChild=Fsm_addChild; pFsm->RemoveChild=Fsm_removeChild; pFsm->Dispatch=Fsm_dispatch; pFsm->Transfer=Fsm_transfer; pFsm->TransferWithEvent=Fsm_transferWithEvent; /*輸出*/ *ppFsm=pFsm; returntrue; }
調(diào)度狀態(tài)機(jī):
/****************************************************************************** *描述:調(diào)度狀態(tài)機(jī) *參數(shù):(in)-pFsm 狀態(tài)機(jī)指針 *(in)-signal調(diào)度信號(hào) *返回:-true 成功 *-false失敗 ******************************************************************************/ boolFsm_dispatch(Fsm*constpFsm,FsmSignalconstsignal) { /*返回結(jié)果*/ boolres=false; ZF_ASSERT(pFsm!=(Fsm*)0) if(pFsm->IsRunning) { if(pFsm->ChildList!=NULL&&pFsm->ChildList->Count>0) { uint32_ti; Fsm*pChildFsm; for(i=0;iChildList->Count;i++) { pChildFsm=(Fsm*)pFsm->ChildList ->GetElementDataAt(pFsm->ChildList,i); if(pChildFsm!=NULL) { Fsm_dispatch(pChildFsm,signal); } } } if(pFsm->CurrentState!=NULL) { /*1:根狀態(tài)機(jī)時(shí)調(diào)度 2:沒設(shè)置觸發(fā)狀態(tài)時(shí)調(diào)度 3:正在觸發(fā)狀態(tài)時(shí)調(diào)度 */ if(pFsm->Owner==NULL||pFsm->OwnerTriggerState==NULL ||pFsm->OwnerTriggerState==pFsm->Owner->CurrentState) { pFsm->CurrentState(pFsm,signal); res=true; } } } returnres; }
篇幅有限,其它接口實(shí)現(xiàn)可閱讀:
https://github.com/54zorb/Zorb-Framework
狀態(tài)機(jī)測(cè)試
/** ***************************************************************************** *@fileapp_fsm.c *@authorZorb *@versionV1.0.0 *@date2018-06-28 *@brief狀態(tài)機(jī)測(cè)試的實(shí)現(xiàn) ***************************************************************************** *@history * *1.Date:2018-06-28 *Author:Zorb *Modification:建立文件 * ***************************************************************************** */ #include"app_fsm.h" #include"zf_includes.h" /*定義用戶信號(hào)*/ enumSignal { SAY_HELLO=FSM_USER_SIG_START }; Fsm*pFsm;/*父狀態(tài)機(jī)*/ Fsm*pFsmSon;/*子狀態(tài)機(jī)*/ /*父狀態(tài)機(jī)狀態(tài)1*/ staticvoidState1(Fsm*constpFsm,FsmSignalconstfsmSignal); /*父狀態(tài)機(jī)狀態(tài)2*/ staticvoidState2(Fsm*constpFsm,FsmSignalconstfsmSignal); /****************************************************************************** *描述:父狀態(tài)機(jī)狀態(tài)1 *參數(shù):-pFsm 當(dāng)前狀態(tài)機(jī) *-fsmSignal當(dāng)前調(diào)度信號(hào) *返回:無(wú) ******************************************************************************/ staticvoidState1(Fsm*constpFsm,FsmSignalconstfsmSignal) { switch(fsmSignal) { caseFSM_ENTER_SIG: ZF_DEBUG(LOG_D,"enterstate1 "); break; caseFSM_EXIT_SIG: ZF_DEBUG(LOG_D,"exitstate1 "); break; caseSAY_HELLO: ZF_DEBUG(LOG_D,"state1sayhello,andwanttobestate2 "); /*切換到狀態(tài)2*/ pFsm->TransferWithEvent(pFsm,State2); break; } } /****************************************************************************** *描述:父狀態(tài)機(jī)狀態(tài)2 *參數(shù):-pFsm 當(dāng)前狀態(tài)機(jī) *-fsmSignal當(dāng)前調(diào)度信號(hào) *返回:無(wú) ******************************************************************************/ staticvoidState2(Fsm*constpFsm,FsmSignalconstfsmSignal) { switch(fsmSignal) { caseFSM_ENTER_SIG: ZF_DEBUG(LOG_D,"enterstate2 "); break; caseFSM_EXIT_SIG: ZF_DEBUG(LOG_D,"exitstate2 "); break; caseSAY_HELLO: ZF_DEBUG(LOG_D,"state2sayhello,andwanttobestate1 "); /*切換到狀態(tài)1*/ pFsm->TransferWithEvent(pFsm,State1); break; } } /****************************************************************************** *描述:子狀態(tài)機(jī)狀態(tài) *參數(shù):-pFsm 當(dāng)前狀態(tài)機(jī) *-fsmSignal當(dāng)前調(diào)度信號(hào) *返回:無(wú) ******************************************************************************/ staticvoidSonState(Fsm*constpFsm,FsmSignalconstfsmSignal) { switch(fsmSignal) { caseSAY_HELLO: ZF_DEBUG(LOG_D,"sonsayhelloonlyinstate2 "); break; } } /****************************************************************************** *描述:任務(wù)初始化 *參數(shù):無(wú) *返回:無(wú) ******************************************************************************/ voidApp_Fsm_init(void) { /*創(chuàng)建父狀態(tài)機(jī),并設(shè)初始狀態(tài)*/ Fsm_create(&pFsm); pFsm->SetInitialState(pFsm,State1); /*創(chuàng)建子狀態(tài)機(jī),并設(shè)初始狀態(tài)*/ Fsm_create(&pFsmSon); pFsmSon->SetInitialState(pFsmSon,SonState); /*設(shè)置子狀態(tài)機(jī)僅在父狀態(tài)State2觸發(fā)*/ pFsmSon->OwnerTriggerState=State2; /*把子狀態(tài)機(jī)添加到父狀態(tài)機(jī)*/ pFsm->AddChild(pFsm,pFsmSon); /*運(yùn)行狀態(tài)機(jī)*/ pFsm->RunAll(pFsm); } /****************************************************************************** *描述:任務(wù)程序 *參數(shù):無(wú) *返回:無(wú) ******************************************************************************/ voidApp_Fsm_process(void) { ZF_DELAY_MS(1000); /*每1000ms調(diào)度狀態(tài)機(jī),發(fā)送SAY_HELLO信號(hào)*/ pFsm->Dispatch(pFsm,SAY_HELLO); } /********************************ENDOFFILE********************************/
結(jié)果:
-
單片機(jī)
+關(guān)注
關(guān)注
6037文章
44558瀏覽量
635214 -
嵌入式
+關(guān)注
關(guān)注
5082文章
19123瀏覽量
305147 -
Switch
+關(guān)注
關(guān)注
1文章
533瀏覽量
58235 -
狀態(tài)機(jī)
+關(guān)注
關(guān)注
2文章
492瀏覽量
27539
原文標(biāo)題:?jiǎn)纹瑱C(jī)最好用的程序框架,莫過(guò)于狀態(tài)機(jī)了
文章出處:【微信號(hào):玩轉(zhuǎn)嵌入式,微信公眾號(hào):玩轉(zhuǎn)嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論