性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

程序小白
認(rèn)證:優(yōu)質(zhì)創(chuàng)作者
所在專題目錄 查看專題
【第一章】有限狀態(tài)機(jī)理論速成筆記
【第二章】HSM層次式狀態(tài)機(jī)理論(進(jìn)階版)
【第三章】有限狀態(tài)機(jī)(FSM)之炸彈項(xiàng)目(實(shí)戰(zhàn)1)
【第四章】有限狀態(tài)機(jī)(FSM)之炸彈項(xiàng)目(實(shí)戰(zhàn)2)
【第五章】有限狀態(tài)機(jī)(FSM)之炸彈項(xiàng)目(實(shí)戰(zhàn)3)
【第六章】層次式狀態(tài)機(jī)HSM = 有限狀態(tài)機(jī)FSM + 面向?qū)ο?
作者動(dòng)態(tài) 更多
基于stm32采用PWM驅(qū)動(dòng)伺服控制器學(xué)習(xí)筆記
5天前
基于STM32驅(qū)動(dòng)TM1638學(xué)習(xí)筆記——軟件篇
04-19 12:42
基于TM1638驅(qū)動(dòng)8位數(shù)碼管設(shè)計(jì)分享
02-24 11:26
RT-Thread驅(qū)動(dòng)之路: Studio創(chuàng)建FAL分區(qū)⑤
01-02 08:30
RT-Thread驅(qū)動(dòng)之路: Studio 掛載通用SPI flash④
2024-12-23 13:41

【第五章】有限狀態(tài)機(jī)(FSM)之炸彈項(xiàng)目(實(shí)戰(zhàn)3)

     我也不知道你能不能堅(jiān)持看到這里,我以為的驚喜,可能對(duì)你來(lái)說(shuō)是一本天書(shū)(是我講的不好),這可能是我最大的遺憾,做技術(shù),痛苦的是無(wú)止盡的重復(fù)做項(xiàng)目,快樂(lè)的是掌握一種新技術(shù),它不能讓你變得富有,只是為你將眼前的大門多推開(kāi)了一丟丟~!沒(méi)有什么能比一句我已經(jīng)在路上了,更能讓人興奮的。

                                                                                          ———程序小白               

                                                                                                        2020.09.08

      繼續(xù)我們的炸彈項(xiàng)目,首先我們要講一下第三種狀態(tài)機(jī)的構(gòu)造模式,就是基于面向?qū)ο蟮乃枷雭?lái)實(shí)現(xiàn)我們的有限狀態(tài)機(jī),這里用到的是完全的面向?qū)ο?,例如在我們的GUI系統(tǒng)中基于事件驅(qū)動(dòng)型設(shè)計(jì)FSM(現(xiàn)實(shí)中可能比這復(fù)雜的多,但也算是種一粒種子吧,萬(wàn)一哪天你真的要搞呢)。這里用到的并不是C語(yǔ)言,因?yàn)镃語(yǔ)言在實(shí)現(xiàn)多態(tài)方面會(huì)很復(fù)雜,不如直接使用C++(C的哥哥),我們先看一下基于面向?qū)ο笤O(shè)計(jì)的QEP的構(gòu)架,如下圖:

      BombState是一個(gè)類,這是一個(gè)抽象類,基于這個(gè)類派生出兩個(gè)子類,SettingState和TimingState,基于這兩個(gè)子類,實(shí)例化兩個(gè)對(duì)象,同時(shí)構(gòu)建我們的Bomb3狀態(tài)機(jī)類,該類的成員中有BombState類型的成員,實(shí)際以指針的方式定義,在狀態(tài)機(jī)運(yùn)行時(shí),改變狀態(tài),實(shí)際就是改變指針來(lái)指向不同的對(duì)象, 通過(guò)其重載的函數(shù)(以多態(tài)的形式),來(lái)實(shí)現(xiàn)不同的狀態(tài)處理函數(shù),這種方式利用C++可以很容易的實(shí)現(xiàn),我們并不做過(guò)多的討論。

      總結(jié)一下:基于面向?qū)ο箢愋偷恼Z(yǔ)言(例如C++)來(lái)實(shí)現(xiàn)狀態(tài)機(jī),實(shí)際可以做的更簡(jiǎn)單,雖然C++學(xué)起來(lái)并不簡(jiǎn)單。

      以上三種方式都稱不上完美,第三種嚴(yán)重依賴C++,我們的目的是用C來(lái)實(shí)現(xiàn)一個(gè)通用的QEP,實(shí)際上一個(gè)通用的QEP集成了以上三種方式的優(yōu)勢(shì),他的構(gòu)架來(lái)了,如下:

      很重要的題外話:QEP事件處理器是QP構(gòu)架的一部分,除了他之外,還有QK(內(nèi)核),QF(框架服務(wù)),上圖中我們能看到分為QEP部分,和應(yīng)用程序部分,也就是如何在我們的應(yīng)用程序中使用構(gòu)架服務(wù),主要應(yīng)用C語(yǔ)言的單繼承,利用繼承,你就可以使用構(gòu)架的服務(wù)。

      接下來(lái)進(jìn)入我們的主題基于通用版QEP實(shí)現(xiàn)的QFSM,代碼講解部分我們以QP5.3.1為模板(QP所有的歷史版本都可以從官網(wǎng)下載到),為什么不以QP6.9.0為模板講,并不是因?yàn)樾碌牟缓茫切碌膭h掉了BOMB的例子,我們無(wú)處可講,所以只能用老版本,實(shí)戰(zhàn)應(yīng)用的話建議大家應(yīng)用新版本,因?yàn)槊恳淮蔚母驴倳?huì)帶來(lái)驚喜。

      首先從簡(jiǎn)單的QEvent事件結(jié)構(gòu)開(kāi)始,分析,在新版本中改名字了,更簡(jiǎn)潔叫QEvt,對(duì)比一下文檔中的樣子和實(shí)際版本中的樣子,如下:

       書(shū)中的版本:

      QP5.3.1中的版本:

      雖然擴(kuò)展的變量不一樣了,但并沒(méi)有復(fù)雜多少,可以先忽略。

      函數(shù)指針類型定義,書(shū)中版本和QP5.3.1區(qū)別不大,如下:

      接下來(lái)使我們的QFSM了,這里的差別就大了,其實(shí)在是實(shí)戰(zhàn)中QFSM的應(yīng)用意義并不大,所以升級(jí)版把他融合到了 HSM中,作為了層次式狀態(tài)機(jī)的子集,理解這段話你就理解了新版本更新后差別出在哪里。

      文檔中的版本,還保存著其本真的東西,如下:

      接下來(lái)我們看看真實(shí)的QP5.3.1中他是什么樣子,如下

      神奇的事情發(fā)生了,F(xiàn)SM和HSM居然都是一個(gè)MSM的別名,也就是兩者居然是一樣的,其實(shí)就是我們前面講的,以前可能分兩個(gè)狀態(tài)機(jī)結(jié)構(gòu),現(xiàn)在通過(guò)一個(gè)MSM實(shí)現(xiàn)了兩者的融合,那么在程序看來(lái),一個(gè)MSM既可以當(dāng)做FSM也可以當(dāng)做HSM,這樣做會(huì)有個(gè)缺點(diǎn),就是MSM有點(diǎn)復(fù)雜和有點(diǎn)大。如下:

      挺復(fù)雜,那么我們只關(guān)注成員state,繼續(xù)跟蹤他的結(jié)構(gòu),如下:

      

      看不懂的部分,直接忽略掉,他的意義當(dāng)我們用到的時(shí)候會(huì)再講,看一下其成員fun的類型,就是我們的函數(shù)指針了。

      接下來(lái)還有FSM必要的三個(gè)函數(shù),來(lái)支持其功能,ctor構(gòu)造,init初始化,dispatch事件分發(fā),這里我們不再對(duì)比文檔中的代碼,那個(gè)相對(duì)簡(jiǎn)單,而且太老版本支持,我們直接上QP5.3.1,如下:

      定義在這個(gè)文件中,路徑如下:

這個(gè)定義很神奇,我們?cè)拘枰P(guān)注的ctor中me->temp.fun = initial;這一句,但是在構(gòu)造函數(shù)中,除了構(gòu)造我們的初始狀態(tài)以外,還幫我們綁定了init初始化和事件分發(fā)函數(shù),很驚喜也很以外。

      接下來(lái)我們看看這個(gè)init函數(shù),定義如下:

這個(gè)函數(shù)一看巨復(fù)雜,QS開(kāi)頭的是軟件追蹤部分代碼,忽略,重要的部分,

/*執(zhí)行具體的初始化函數(shù),例如我們的bomb4代碼中的init,要求我們初始化函數(shù)必須返回Q_RET_TRAN*/

(*me->temp.fun)(me,e) == (QState)Q_RET_TRAN

完成初始化,觸發(fā)一個(gè)Q_ENTRY_SIG事件,接收該事件的時(shí)間處理函數(shù)為me-temp.fun

也就是執(zhí)行temp.fun的進(jìn)入動(dòng)作,如下:

(void)QEP_TRIG_(me-temp.fun,Q_ENTRY_SIG);這是一個(gè)宏,展開(kāi)后

執(zhí)行完畢,后temp.fun更新到state.fun中。

最后還有一個(gè)函數(shù)沒(méi)有講,dispatch,我先找找他在哪,如下:

這個(gè)函數(shù)有點(diǎn)復(fù)雜,但我還是能看得懂,真到了HSM說(shuō)實(shí)話,我真沒(méi)看懂,我也不斷講HSM中dispatch的實(shí)現(xiàn),說(shuō)實(shí)話太復(fù)雜了,能學(xué)會(huì)說(shuō)明你算法基礎(chǔ)好,到哪里我們只講規(guī)則,如何應(yīng)用,不講實(shí)現(xiàn),有興趣筒子們自己研究源碼,這里我們把FSM的dispatch貼出來(lái),如下:

      代碼很長(zhǎng),其實(shí)很簡(jiǎn)單,首先進(jìn)入的時(shí)候,有兩個(gè)狀態(tài)處理函數(shù),代碼兩個(gè)狀態(tài),state和temp,這倆咋進(jìn)入的時(shí)候是相等的 ,會(huì)有一個(gè)斷言判斷,如果不相等,那么說(shuō)明狀態(tài)機(jī)有異常,如下:

      68:Q_REQUIRE_ID(100, me->state.fun == me->temp.fun);

      接下來(lái)執(zhí)行事件處理函數(shù),返回狀態(tài)很重要,r很重要,如下:

         r = (*me->state.fun)(me, e); /* call the event handler */

      如果if (r != (QState)Q_RET_TRAN),dispatch就結(jié)束了,如果發(fā)生了轉(zhuǎn)換,

那么先執(zhí)行源的退出,在執(zhí)行目標(biāo)的進(jìn)入,最后再把目標(biāo)賦值給源,完成了狀態(tài)轉(zhuǎn)換,如下,

      QEP_EXIT_(me->state.fun); /* exit the source */

      QEP_ENTER_(me->temp.fun); /* enter the target */

      me->state.fun = me->temp.fun; /* record the new active state */

到這里一個(gè)完整的QFSM(基于QEP)講完了,上面講的這些都不需要我們?nèi)ゾ幋a,這是框架的部分,QP幫我們寫好了,直接應(yīng)用就好了,假如你真的按我的步驟把QPC5.3.1的這部分代碼通讀了一遍,那么,關(guān)于bomb如何基于他實(shí)現(xiàn),就不需要任何言語(yǔ)了,直接上代碼.

      bomb第一部分,如下:

      第二部分,如下:

main.c如下:

      基于通用的QEP實(shí)現(xiàn)的bomb,到此完結(jié),再見(jiàn)~!

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場(chǎng)。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺(jué)得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 6
收藏 7
關(guān)注 150
成為作者 賺取收益
全部留言
0/200
  • 星球居民-MpJKwDuF 2020-10-05 11:10
    看不太懂
    回復(fù)