有限狀態(tài)機是根據當前狀態(tài)以及觸發(fā)條件進(jìn)行狀態(tài)轉換的一種機制,包含一組狀態(tài)集(state)、一個(gè)起始狀態(tài)(start state)、一組輸入符號集(alphabet)、一個(gè)映射輸入符號和當前狀態(tài)到下一狀態(tài)的轉換函數(transition function)的計算模型[1]。當輸入符號串時(shí),模型隨即進(jìn)入起始狀態(tài)。要讓狀態(tài)機改變到新的狀態(tài),依賴(lài)于系統的轉換函數。有限狀態(tài)機中有許多變量,例如,與動(dòng)作(actions)轉換(Mealy機)或狀態(tài)(摩爾機)關(guān)聯(lián)的動(dòng)作,多重起始狀態(tài),基于沒(méi)有輸入符號的轉換或指定符號和狀態(tài)(非定有限狀態(tài)機)的多個(gè)轉換、指派給接收狀態(tài)(識別者)的一個(gè)或多個(gè)狀態(tài)。有限狀態(tài)機多應用于硬件時(shí)序電路設計。 有限狀態(tài)機也可以應用到嵌入式軟件設計中。在進(jìn)行嵌入式軟件設計時(shí),通常的做法是按照信息流程進(jìn)行順序編程。例如對串行數據的處理,一般是等待接收數據,分析數據,進(jìn)行數據處理,然后發(fā)送處理結果。使用這種軟件設計方法,最突出的一點(diǎn)就是在任務(wù)的處理過(guò)程中,任務(wù)基本上獨占了MCU的資源,即在處理串口數據的過(guò)程中,不會(huì )再去處理其他消息(中斷除外)。采用這種方式,MCU會(huì )在相當長(cháng)的一段時(shí)間內只處理一個(gè)任務(wù)。如果合理運用狀態(tài)機機制開(kāi)發(fā)系統軟件,就可以讓MCU進(jìn)行多任務(wù)的分時(shí)處理。 1 建立有限狀態(tài)機的模型 其實(shí)在平時(shí)的程序設計中,開(kāi)發(fā)人員已經(jīng)不知不覺(jué)地使用了狀態(tài)機,如按鍵狀態(tài)轉換、菜單顯示狀態(tài)的轉換等。但是,很少有系統會(huì )使用狀態(tài)機進(jìn)行多任務(wù)處理。在單片機系統中,通過(guò)對系統各功能模塊的分析,可以建立有限狀態(tài)機的模型,繼而在系統的軟件設計中利用狀態(tài)機的特點(diǎn),開(kāi)發(fā)出結構清晰的高效率嵌入式軟件。 1.1 系統功能分析 具有GPS、GPRS功能的公交車(chē)智能IC卡收費機,其功能包括對乘客使用的非接觸式IC卡進(jìn)行刷卡消費,使用GPS進(jìn)行自動(dòng)報站[2],以及使用GPRS進(jìn)行實(shí)時(shí)調度[3]等。按照獨占式處理模式,智能收費機的軟件系統會(huì )把多個(gè)任務(wù)按照信息流程進(jìn)行排隊,處理完一個(gè)任務(wù)后,再進(jìn)行下一個(gè)任務(wù)的處理。使用狀態(tài)機進(jìn)行軟件編程,可以把每一個(gè)任務(wù)分解為多個(gè)狀態(tài),在某個(gè)狀態(tài)處理時(shí),同時(shí)檢查其他任務(wù)是否需要進(jìn)行信息處理,并進(jìn)行狀態(tài)的轉換。這樣就可以讓MCU在等待的空閑時(shí)間內進(jìn)行多個(gè)消息的處理。 1.2 IC卡功能的狀態(tài)機建模 目前公交車(chē)乘客使用的公交卡,一般都是非接觸式IC卡,需要使用一個(gè)接口芯片對卡片進(jìn)行讀寫(xiě)操作。因此要對IC卡進(jìn)行操作,就需要先對接口芯片進(jìn)行初始化,包括對相關(guān)I/O引腳的設置、訪(fǎng)問(wèn)地址的設定等操作。當非接觸式IC卡進(jìn)入無(wú)線(xiàn)操作范圍后,需要使用Request命令喚醒卡片,再對喚醒的卡片(一張或多張)進(jìn)行防沖突處理,得到卡片的唯一標識碼,然后通過(guò)Select命令選擇要進(jìn)行操作的卡片。非接觸式IC卡內的數據是用密碼進(jìn)行保護的,而且每個(gè)區的密碼都不一樣。因此在對某個(gè)區進(jìn)行讀寫(xiě)前,還需要進(jìn)行密碼的驗證。只有密碼正確了,才可以進(jìn)行讀寫(xiě)操作。如果卡片的防沖突處理、選擇卡片操作扇區、授權驗證這幾個(gè)步驟出錯,則需要使用Request命令對卡片重新喚醒,然后再進(jìn)行其他操作。在完成對卡片某一區域的讀寫(xiě)后,可以直接對其他區域進(jìn)行操作(需要重新驗證密碼),或者使用Request命令對其他卡片進(jìn)行操作[4]。 對IC卡的操作可以分為以下幾個(gè)部分:接口芯片的初始化、查詢(xún)卡片、防沖突處理、選擇卡片、對操作扇區授權驗證、讀卡、寫(xiě)卡。根據對IC卡的操作,可以建立IC卡操作的相應狀態(tài)作為狀態(tài)機。建立狀態(tài)機的模型如圖1所示。類(lèi)似地,對于GPRS、GPS等功能模塊,也可以進(jìn)行相應的狀態(tài)機建模。 ![]() 圖1 非接觸IC卡操作的狀態(tài)機 2 利用狀態(tài)機進(jìn)行軟件設計 利用前面所建立的狀態(tài)機模型,可以方便地進(jìn)行相應的程序設計。軟件的主要工作是進(jìn)行正確的狀態(tài)切換和在每個(gè)狀態(tài)下執行相應的動(dòng)作。對單個(gè)狀態(tài)機處理的程序設計,可以使用“橫式”或“豎式”兩種設計方法!皺M式”設計是把每個(gè)狀態(tài)的功能作為一個(gè)子函數處理,在子函數外部進(jìn)行狀態(tài)的切換!柏Q式”設計是在單個(gè)switch語(yǔ)句中對所有的狀態(tài)進(jìn)行判斷,執行相應動(dòng)作并進(jìn)行狀態(tài)切換。 下面以非接觸式IC卡操作為例,對兩種軟件設計方式進(jìn)行討論。假設變量如下:當前狀態(tài)為cur_state,下一狀態(tài)為next_state;狀態(tài)分別為RC500Config、RC500Request、RC500Anticoll、RC500Select、RC500Auth、 RC500LoadMk、RC500Read、RC500Write。[5]“豎式”程序設計如下: switch(cur_state){//在當前狀態(tài)中判斷事件 case RC500Config://進(jìn)行RC500Config初始化狀態(tài) 執行初始化動(dòng)作 if(SUCCESS){ next_state = RC500Request;//成功則進(jìn)行卡片查詢(xún) } else{ 斷電重新初始化 } break; case RC500Request://在RC500Request狀態(tài) 對射頻范圍內的卡片進(jìn)行查詢(xún) if(SUCCESS){ //將狀態(tài)轉移到RC500Anticoll態(tài) next_state = RC500Anticoll; } else{ 繼續查詢(xún) } break; case RC500Anticoll://在RC500Anticoll狀態(tài) 進(jìn)行抗沖突處理 if(SUCCESS){ 獲取卡片識別碼,轉到選擇卡片狀態(tài) next_state = RC500Select; } case … } “橫式”設計是把每個(gè)狀態(tài)及所要執行的動(dòng)作單獨放到一個(gè)子函數中處理,有RC500Config()、RC500Request()、 RC500Anticoll()等。工作狀態(tài)的確定可以通過(guò)查詢(xún)狀態(tài)表獲得,找到相應的狀態(tài)后運行相應的子函數。在每個(gè)子函數中,既有該狀態(tài)下應該執行的動(dòng)作,也有狀態(tài)的轉換。然后在主程序中判斷狀態(tài)是否發(fā)生了轉換,再轉到相應的狀態(tài)子程序中執行。 橫豎兩種寫(xiě)法,實(shí)現的功能完全相同,但是“豎式”隱含了優(yōu)先級排序,破壞了事件間原有的關(guān)系。同時(shí),由于處在每個(gè)狀態(tài)的事件數目不一致,而且事件發(fā)生的時(shí)間是隨機的,“豎式”設計為順序查詢(xún)方式,因此大量時(shí)間被浪費!皺M式”設計,在某個(gè)時(shí)間點(diǎn)狀態(tài)是唯一確定的,延遲時(shí)間可以預先準確估算。而且在事件發(fā)生時(shí),系統會(huì )調用相應的事件函數,在函數里查找唯一確定的狀態(tài),并根據其狀態(tài)執行動(dòng)作和狀態(tài)轉移。使用這種方式設計的軟件思路清晰簡(jiǎn)潔,效率高,故使用“橫式”方法設計程序更好。 類(lèi)似地,對于GPRS、GPS等功能模塊也可以運用狀態(tài)機機制進(jìn)行程序設計,從而在整個(gè)智能收費機的軟件設計中,對所有任務(wù)的處理都可以運用狀態(tài)機機制進(jìn)行相應的程序設計。 3 使用狀態(tài)機的效能分析 在很多嵌入式系統軟件設計中都可以用到類(lèi)似狀態(tài)機的設計思想,比較常用的地方就是各種液晶界面的設計。使用狀態(tài)機機制設計軟件,可以使設計思路清晰、靈活,軟件的可讀性強,便于以后的維護。如果合理地使用狀態(tài)機,還可以較大幅度地提高M(jìn)CU的運行效率。下面以非接觸式IC卡的軟件設計流程為例討論。 ![]() 圖2 嵌入式軟件設計方法比較 圖2(a)是傳統的嵌入式軟件設計流程,使用這種流程設計的系統軟件按部就班地先執行RC500Config(),再執行 RC500Request(),然后是RC500Anticoll(),直到對IC卡操作完成,再轉到其他任務(wù)(如GPS)。這樣IC卡的操作任務(wù)占用了整個(gè)MCU資源。圖2(b)是使用狀態(tài)機設計系統軟件的流程。在使用狀態(tài)機的同時(shí)設定一個(gè)軟件時(shí)鐘,用來(lái)為系統的各個(gè)任務(wù)進(jìn)行計時(shí),并進(jìn)行任務(wù)的調度。軟件時(shí)鐘使用一個(gè)長(cháng)整型變量進(jìn)行計時(shí),利用MCU定時(shí)器1 ms或10 ms的中斷來(lái)實(shí)現,從而使時(shí)鐘不受任務(wù)執行過(guò)程的影響。當某個(gè)任務(wù)執行過(guò)程需要等待延時(shí),執行子函數返回main()函數,讓其他任務(wù)使用MCU資源。這樣實(shí)現的軟件,在處理某個(gè)任務(wù)的空隙可以同時(shí)處理其他任務(wù)的操作,有效地提高了MCU處理事件的能力。具體實(shí)現方法如下: RC500Request(){ time_mark = mS_mark;//若需要延時(shí),更新計時(shí)的軟件時(shí)間 …… if(!past_200mS())break;//如果延時(shí)不足200 ms,//返回調用函數,MCU運行其他任務(wù) …… } 當延時(shí)不夠200 ms時(shí),函數RC500Request()直接返回而沒(méi)有改變IC卡操作的狀態(tài),因此MCU下一次進(jìn)行IC卡操作時(shí),繼續執行函數 RC500Request(),直到IC卡操作狀態(tài)改變。同時(shí),函數RC500Request()返回后,main()函數會(huì )檢查GPS、GPRS等工作模塊,執行其中的某些動(dòng)作。也就是說(shuō),在執行IC卡操作的同時(shí),可以執行其他任務(wù)的操作;同理,在執行其他任務(wù)的操作時(shí),也可以執行IC卡的一些操作。這樣就可以充分利用MCU的資源,提高M(jìn)CU對多任務(wù)的處理效率。 結語(yǔ) 使用上述狀態(tài)機機制設計的智能公交車(chē)IC卡收費機的系統軟件,能夠及時(shí)處理IC卡信息、GPS定位信息、GPRS通信等多個(gè)任務(wù)的操作,運行穩定,完全滿(mǎn)足實(shí)際應用的要求。該機制非常適合功能較多的嵌入式軟件系統設計。 參考文獻 1. 夏宇聞 復雜數字電路與系統的Verilog HDL設計技術(shù) 1998 2. Falcom Inc JP-13 datasheet 2005 3. Siemens AG MC55 / MC56 AT Command Set 2005 4. Philips Inc Mifare MFRC531 User Manual 2003 5. 徐愛(ài)鈞.彭秀華 單片機高級語(yǔ)言C51應用程序設計 1998 作者:山東政法學(xué)院 楊瑞霞 來(lái)源:?jiǎn)纹瑱C與嵌入式系統應用 2009(5) |