版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?
<http://creativecommons.org/licenses/by-sa/4.0/>版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。
本文鏈接:https://www.cnblogs.com/lihuidashen/p/11510532.html
<https://www.cnblogs.com/lihuidashen/p/11510532.html>
https://mp.weixin.qq.com/s/xDAfaEFY4INHzr7MFnR5dg
<https://mp.weixin.qq.com/s/xDAfaEFY4INHzr7MFnR5dg>
?
????關(guān)于狀態(tài)機(jī),基礎(chǔ)的知識點可以自行理解,講解的很多,這里主要是想寫一個有限狀態(tài)機(jī)FSM通用的寫法,目的在于更好理解,移植,節(jié)省代碼閱讀與調(diào)試時間,體現(xiàn)出編程之美。
?
傳統(tǒng)的實現(xiàn)方案
*
if...else : 搞一大堆if else, 一個函數(shù)寫很長很長......
*
swich...case : 也搞一大堆一個函數(shù)寫很長很長......
?
????先來看看最近做的一個項目,無線通信協(xié)議實現(xiàn)的狀態(tài)機(jī)是什么樣子的:
?
?
????有三種類型的事件:上層下達(dá)的命令事件;下層到達(dá)的標(biāo)志和數(shù)據(jù)傳輸事件;超時定時器超時事件。有10種狀態(tài),關(guān)聯(lián)性很大,復(fù)雜了吧,這要是各種if/else的要寫到什么時候呢。
?
? ? 偷偷放一張討論的圖,亂七八糟形容很恰當(dāng)。
?
????在事件中判斷狀態(tài),在狀態(tài)中判斷事件,橫豎兩種寫法的代碼都比較冗長,看起來呢也不大好,一旦增減,就又要動腦子重新梳理一遍,很累的。
?
????怎么去寫呢?其狀態(tài)機(jī)原理:在根據(jù)當(dāng)前狀態(tài)(cur_state)
下,發(fā)生事件(event)后,轉(zhuǎn)移到下一個狀態(tài)號(nxt_state),決定執(zhí)行的動作(action)。盜用一個圖吧
?
?
????這里我們首先定義一個結(jié)構(gòu)體如下:
typedef struct { State curState;//當(dāng)前狀態(tài) EventID eventId;//事件ID State nextState;
//下個狀態(tài) Action action;//具體表現(xiàn)} StateTransform;
?
?
????我們假設(shè)有3種狀態(tài),這里可以隨意增加,狀態(tài)枚舉如下:
typedef enum { state_1=1, state_2, state_3} State;
?
????我們假設(shè)有5個事件,也可以隨意增加,事件ID枚舉如下:
typedef enum{ event_1=1, event_2, event_3, event_4, event_5}EventID;
?
????將其封裝起來在StateMachine中:
typedef struct{ State state; int transNum; StateTransform* transform;
}StateMachine;
?
?
????具體流程:當(dāng)前狀態(tài)-有事件觸發(fā)-跳到下個狀態(tài)-具體表現(xiàn),重構(gòu)代碼
StateTransform* findTranss(StateMachine* pSM, const EventID evt){ int i; for
(i =0; i < pSM->transNum; i++) { if ((pSM->transform[i].curState == pSM->state)
&& (pSM->transform[i].eventId == evt)) { return &pSM->transform[i]; } } return
NULL; }
?
????狀態(tài)機(jī)實現(xiàn)如下:
StateTransformm* pTrans; pTrans = findTrans(pSM, evt); if (pTrans == NULL) {
xil_printf("CurState= %s Do not process enent: %s\r\n", pSM->state,evt); return
; } pSM->state = pTrans->nextState; Action act = pTrans->action; if (act ==
NULL) { xil_printf("change state to %s. No action\r\n",pSM->state); return; }
act(&evt);
?
????最后我模擬一些隨機(jī)事件,我們只需要弄清楚事件ID,狀態(tài)切換,具體表現(xiàn)就可以了,在代碼中就是填寫 stateTran[] 這個表
,一旦有增減事件,狀態(tài)等等,也不需要再去使用switch/case,特費(fèi)腦,其代碼如下:
int run() { StateMachine stateMachine; stateMachine.state = state_1;
stateMachine.transNum= 7; StateTransform stateTran[] = {
{state_1,event_3,state_2,f121}, {state_1,event_4,state_2,NULL},
{state_2,event_1,state_3,f231}, {state_2,event_4,state_2,f221},
{state_3,event_2,state_1,f311}, {state_3,event_3,state_2,f321},
{state_3,event_5,state_3,f331} }; stateMachine.transform= stateTran; EventID
inputEvent[15] = { event_1, event_2, event_3, event_4, event_5, event_1,
event_2, event_3, event_4, event_5, event_1, event_2, event_3, event_4, event_5
};int i; for (i = 0; i < 15; i++) { runStateMachine(&stateMachine,
inputEvent[i]); }return 0; }
?
????最后運(yùn)行結(jié)果如下
?
?
總結(jié):
?? ?狀態(tài)機(jī)應(yīng)用很廣泛,也可以鍛煉我們寫代碼的邏輯思維,看清問題的本質(zhì),寫的代碼才能賞心悅目,希望大家能夠多多指點,找到編程的樂趣,欣賞到編程之美。
?
推薦閱讀
FPGA 高手養(yǎng)成記-Verliog語法基礎(chǔ)
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247484062&idx=1&sn=8a871531f31a7513236654d1bda3d1e3&chksm=97584a6ca02fc37a1db431685d689241f6a89bb5f0549a300ab7bd1fcb7d659fe1f62a19ec5a&scene=21#wechat_redirect>
FPGA 高手養(yǎng)成記-淺談狀態(tài)機(jī)
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247484095&idx=1&sn=5e82fbb0648da16e079488ec646c6ac8&chksm=97584a4da02fc35b803c9289a872f67950bc53f53854f3dad3e9a15b227c97e402bc6800aa32&scene=21#wechat_redirect>
FPGA 高手養(yǎng)成記-Test bench文件結(jié)構(gòu)一覽無余
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247484150&idx=1&sn=f8c079d12898a541991c930c1ed29e4a&chksm=97584a04a02fc31201604dea5fbfcdf01f23fa6986d3e1f8e4549ece1acee33c3813d8943e31&scene=21#wechat_redirect>
FPGA 高手養(yǎng)成記-【很重要】Testbenth前仿真全過程
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247484168&idx=1&sn=0f250add9f1dec4d33ad48c78a8c81f4&chksm=97584bfaa02fc2ecbef31ccacd57c58401e9e414ca0a70ae133ae8fe13777d77ad9f995668f5&scene=21#wechat_redirect>
const 指針與指向const的指針
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247484016&idx=1&sn=f3f723a30dbb50811d4ac48afd028ac6&chksm=97584a82a02fc39463e536310a061a1cfcf8adc21b1d1de34c7c5d4a9cd1cfeb0dc164afbe47&scene=21#wechat_redirect>
蛻變成蝶~Linux設(shè)備驅(qū)動之字符設(shè)備驅(qū)動
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247483912&idx=1&sn=4ac95f580a2fc7d51157a4fb651354f4&chksm=97584afaa02fc3eca1b6d4218e8399a6d2c42857558630001d8de3660b9502e0023d2e44759b&scene=21#wechat_redirect>
24小時學(xué)通Linux內(nèi)核--內(nèi)核探索工具類
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247483834&idx=1&sn=2bb49a10cbbc10d146a2da2705a774b7&chksm=97584948a02fc05ef8b385c9f8b61888c23aa7fc101e655af0d9f2bdad892712e330b0f785c2&scene=21#wechat_redirect>
機(jī)器學(xué)習(xí)理論提升方法AdaBoost算法第一卷
<http://mp.weixin.qq.com/s?__biz=MzIxMTE5ODM2NQ==&mid=2247483973&idx=1&sn=6ad3c88e18b74bdc7be711b8effdfdf2&chksm=97584ab7a02fc3a1ee423ba6aa4d1e3c1cb5fa1b8dcc5cfc28673e1023941af3bad45cbb03ca&scene=21#wechat_redirect>
?
關(guān)注公眾號【技術(shù)讓夢想更偉大】,獲取更多Linux/C/C++/Python/FPGA等原創(chuàng)技術(shù)文章。后臺免費(fèi)獲取經(jīng)典電子書籍和視頻資源,實時更新,原創(chuàng)不易,請多支持,謝謝!
?
熱門工具 換一換