嚴格意義上來講,狀態(tài)機理論應(yīng)該屬于控制理論的范疇,他其實不光在軟件領(lǐng)域發(fā)光發(fā)熱,實際上他對于硬件設(shè)計更加的重要,多年前我曾讀過分享過那些當年看不懂的文章,依舊給他人很大的幫助。
有興趣的童鞋可以去讀一下,不論你從事軟件還是硬件,都值得一讀,接下來進入正題,我們來速成狀態(tài)機,舉個例子:
早期的狀態(tài)機控制理論(不完整)
地震啦~!?。?! 我:。。。跑~!?。。ㄟ@就是狀態(tài)機的早期的事件動作范型)(缺點:我是誰 ,我在哪 ,我為什么要跑?)
完整的狀態(tài)機模型(完整語義)
地震啦~?。?!
版本一,我:我居然在大樓里~! 跑~?。?!
版本二,我:我在大草原上~!沒事兒~?。?!
這就是完整的狀態(tài)機模型(事件-狀態(tài)-動作范型),看到這里你也就學會了狀態(tài)機,簡不簡單~!是的,狀態(tài)機的初衷就是為了不制造麻煩~!
狀態(tài)機進階(任何理論都會因?qū)嵺`慢慢改進豐富和進階):
普通版狀態(tài)機:
媽媽要出門買雞蛋了,你在家先寫十分鐘的作業(yè),然后就可以看會兒動畫片了, 這時候你躁動了,十分鐘等于六百秒,于是開始1...2...3...600....終于可以看電視了,你再數(shù)數(shù)之前,要先想一下之前數(shù)的是幾(歷史就是狀態(tài)),然后才知道下一個是幾。要完整這件事你要數(shù)600個數(shù),轉(zhuǎn)換600中狀態(tài),什么時候轉(zhuǎn)換呢,你會盯著時鐘的秒表,他動一下,你加一(事件)。結(jié)果媽媽回來,發(fā)現(xiàn)你居然沒有寫作業(yè),于是不光挨了罵,動畫片也看不成了。
擴展狀態(tài)機(進階版):
媽媽要出門買雞蛋了,你在家先寫十分鐘的作業(yè),然后就可以看會兒動畫片了, 你拿過鬧鐘,定了一個十分鐘的鬧鐘,然后繼續(xù)寫作業(yè)(狀態(tài)1),十分鐘后,鬧鐘響了(監(jiān)護條件),時間到啦,你放下作業(yè),打開電視,開始看動畫片(狀態(tài)2),不一會兒媽媽回來了,檢查了你的作業(yè),發(fā)現(xiàn)你很守信用,于是不光讓你多看一會兒電視,而且還獎勵了一根棒棒糖。
總結(jié):并不是所有的狀態(tài)都要被構(gòu)造成狀態(tài)機,如果有很多狀態(tài)其實都是一個簡單的變量維護,那么可以建立一個狀態(tài)機,再其內(nèi)部維護這個變量,創(chuàng)建一個監(jiān)護條件,只有等監(jiān)護條件滿足時,才跳轉(zhuǎn)到其它狀態(tài)機。
注意:在單片機軟件中構(gòu)造一個狀態(tài)機是需要一定內(nèi)存資源開銷的,想想我們那可憐的RAM,一個項目到底要分解成多少個狀態(tài)機不光是技術(shù)問題,更是藝術(shù)問題。
狀態(tài)機中最重要的幾個概念:事件 狀態(tài) 動作 (擴展狀態(tài)機還有監(jiān)護條件)
一個簡單的狀態(tài)機可以如下描述:
狀態(tài)機還有個很重要的概念要RTC(Run-to-Completion):大體意思是運行到完成,這個過程是不可以打斷的,因為如果被打斷了,那么你就恢復(fù)現(xiàn)場,問題就復(fù)雜了,舉個例子,鬧鐘響了(事件發(fā)生),我(睡眠狀態(tài))到(起床狀態(tài))需要完成的RTC如下:
伸懶腰 穿衣 穿鞋 洗漱結(jié)束。假如你在穿衣的過程中,突然接到女神的求助電話,這時候可能直接從床上跳起來,寫也顧不上穿就飛奔而去,這就打亂了我們原本的狀態(tài)機執(zhí)行上下文,導(dǎo)致你鞋沒穿 牙沒刷出門了,理論上這是不允許的,盡管現(xiàn)實中是你想要的。
到這里基本就完成了傳統(tǒng)意義上的FSM(有限狀態(tài)機)的學習,理論的東西,理解就好了,詳細看書可以要花個半天,當然更專業(yè),如下: