狀態機編程
轉載正文2
狀態機思路在單片機程序設計中的應用狀態機的概念狀態機是軟件編程中的一個重要概念。比這個概念更重要的是對它的靈活應用。在一個思路清晰而且高效的程序中,必然有狀態機的身影浮現。比如說一個按鍵命令解析程序,就可以被看做狀態機:本來在A狀態下,觸發一個按鍵后切換到了B狀態;再觸發另一個鍵后切換到C狀態,或者返回到A狀態。這就是最簡單的按鍵狀態機例子。實際的按鍵解析程序會比這更復雜些,但這不影響我們對狀態機的認識。進一步看,擊鍵動作本身也可以看做一個狀態機。一個細小的擊鍵動作包含了:釋放、抖動、閉合、抖動和重新釋放等狀態。同樣,一個串行通信的時序(不管它是遵循何種協議,標準串口也好、I2C也好;也不管它是有線的、還是紅外的、無線的)也都可以看做由一系列有限的狀態構成。顯示掃描程序也是狀態機;通信命令解析程序也是狀態機;甚至連繼電器的吸合/釋放控制、發光管(LED)的亮/滅控制又何嘗不是個狀態機。當我們打開思路,把狀態機作為一種思想導入到程序中去時,就會找到解決問題的一條有效的捷徑。有時候用狀態機的思維去思考程序該干什么,比用控制流程的思維去思考,可能會更有效。這樣一來狀態機便有了更實際的功用。程序其實就是狀態機。也許你還不理解上面這句話。請想想看,計算機的大廈不就是建立在“0”和“1”兩個基本狀態的地基之上么?
狀態機的要素狀態機可歸納為4個要素,即現態、條件、動作、次態。這樣的歸納,主要是出于對狀態機的內在因果關系的考慮。“現態”和“條件”是因,“動作”和“次態”是果。詳解如下:①現態:是指當前所處的狀態。②條件:又稱為“事件”。當一個條件被滿足,將會觸發一個動作,或者執行一次狀態的遷移。③動作:條件滿足后執行的動作。動作執行完畢后,可以遷移到新的狀態,也可以仍舊保持原狀態。動作不是必需的,當條件滿足后,也可以不執行任何動作,直接遷移到新狀態。④次態:條件滿足后要遷往的新狀態。“次態”是相對于“現態”而言的,“次態”一旦被激活,就轉變成新的“現態”了。如果我們進一步歸納,把“現態”和“次態”統一起來,而把“動作”忽略(降格處理),則只剩下兩個最關鍵的要素,即:狀態、遷移條件。狀態機的表示方法有許多種,我們可以用文字、圖形或表格的形式來表示一個狀態機。純粹用文字描述是很低效的,所以就不介紹了。接下來先介紹圖形的方式。
狀態遷移圖(STD)狀態遷移圖(STD),是一種描述系統的狀態、以及相互轉化關系的圖形方式。狀態遷移圖的畫法有許多種,不過一般都大同小異。我們結合一個例子來說明一下它的畫法,如圖1所示。


用狀態機思路實現一個時鐘程序接下來,我將就狀態機的應用,結合流程圖、狀態遷移圖和狀態遷移,舉一個實際例子。下面這張圖是一個時鐘程序的狀態遷移圖,如圖2所示。





轉載正文3
實際的狀態機編程思想例子看看小時候玩的5塊錢那種最簡單的電子表。只有2個按鈕就能操作。暫且稱為按鈕A和按鈕B現給出一個完整的功能文字描述:在顯示時間時按A,屏幕顯示變成日期在顯示日期時按A,屏幕顯示變成秒鐘在顯示秒鐘時按A,屏幕顯示變成時間在顯示秒鐘時按B,秒鐘歸0在顯示時間時按B,屏幕 時間、日期交替顯示。在時間、日期交替顯示時按B,屏幕“時”閃爍在“時”閃爍時按B,屏幕“時”加1,超過23回0在“時”閃爍時按A,屏幕“分”閃爍在“分”閃爍時按B,屏幕“分”加1,超過59回0在“分”閃爍時按A,屏幕“月”閃爍在“月”閃爍時按B,屏幕“月”加1,超過12回0在“月”閃爍時按A,屏幕“日”閃爍在“日”閃爍時按B,屏幕“日”加1,超過31回0在“日”閃爍時按A,屏幕回到時間顯示如果按照新手的思路,嘗試去畫流程圖,很快就會陷入一頭霧水:你會發現實現這個功能的程序根本就沒有“確定的流程”。因為程序實際流程是根據人的操作而變化的。程序運行到什么地方,完全取決于兩個鍵的次序,有無數種次序組合,根本不可能畫出流程圖來。但是我們會發現,這個電子表功能的“語言描述”在語法上似乎有某種規律,就是:當系統處于某狀態(S1)時,如果發生了什么事情(E),就執行某功能(F),然后系統變成新狀態(S2)只要能用上面這句話描述的系統,都可以用一種狀態跳轉機制很方便的實現,并且一句話其實就是一個if(...),無論有多少多復雜的功能,只要能用上面這句話描述,都可以通過狀態機編程實現。 我們將它們抽象。整個系統中有2個事件分別是:A按下,B按下A按下(可以是中斷)時執行:{if(Status==TIME) //當顯示時間時按下A鍵{Status=DATE //變成顯示日期}if(Status==DATE) //當顯示日期時按下A鍵{Status=SEC //變成顯示秒鐘}if(Status==SEC) //當顯示秒鐘時按下A鍵{Status=TIME //變成顯示時間}if(Status==SET_HOUR) //當設置“小時”時按下A鍵{Status=SET_MINUT //變成設置“分鐘”}if(Status==SET_MINUT) //當設置“分鐘”時按下A鍵{Status=SET_MONTH //變成設置“月”}..........}B按下(可以是中斷)時執行:{if(Status==SEC) //當顯示秒鐘時按下B鍵{Secound=0 //秒歸0}if(Status==TIME) //當顯示時間時按下B鍵{Status=TIMEDATE //變成時間日期交替顯示}if(Status==TIMEDATE) //當日期交替顯示時按下B鍵{Status=SET_HOUR //變成設置“時”(時閃爍)}if(Status==SET_HOUR) //當設置“時”時按下B鍵{Status=Hour++ //時加1if(Hour>23) Hour=0; }.......... }和語言描述完全一致,很快就能寫完程序。這就是最簡單的狀態機思想。當然,上述一大堆if可以用switch case來實現實際中,大量的并發過程都可以表述為狀態跳轉關系,從而將CPU從過程中解放出來,只需處理狀態關系,因為真正需要CPU的是狀態變化的時刻,而不是過程中大量的等待,這樣大量的并發過程都可以并行處理。
評論