標籤:enter else top switch語句 流程 理由 排序 控制 idt
停車場門禁控制系統的狀態機器設計
門禁控制系統的輸入訊號包括:
- 起落杆定位感應器:有兩個位置值訊號(升起/落下)
- 汽車入閘感應器:有兩個值(True/False)
- 汽車出閘感應器:有兩個值(True/False)
門禁控制系統的輸出訊號包括:
- 起落杆電機控制訊號:(上升/下降)
- 通行燈訊號:(紅燈/綠燈)
一輛汽車的通過流程為:
- 起落杆處於落下狀態,通行燈為紅燈。
- 汽車進入門禁系統,入閘感應器值變為True。
- 控制起落杆上升,直到起落杆定位感應器到達升起位置。
- 通行燈為綠燈。
- 汽車離開門禁,觸發汽車出閘感應器值為True。
- 控制起落杆下降,直到起落杆定位感應器到達落下位置。
- 通行燈變為紅燈。
所描述的控制系統的狀態機器包括:
- 狀態機器的所有狀態
- 狀態機器所接收到的外來事件
- 狀態機器所產生的動作
- 狀態機器的所有狀態躍遷:(原狀態、新狀態、觸發條件、產生動作)
首先設:
Q1代表可以通行的狀態;
Q2代表不能通行的狀態;
W1代表汽車進入門禁系統這個事件;
W2代表汽車離開門禁系統這個事件;
E1代表起落杆上升,通行燈變綠燈;
E2代表起落杆下降,通行燈變紅燈;
目前狀態 |
Q1 |
Q2 |
事件 |
|
--- |
E1/Q1 |
W1 |
|
E2/Q2 |
--- |
W2 |
豎著寫(在狀態中判斷事件)C程式碼片段:
cur_state = nxt_state;
switch(cur_state) //在目前狀態中判斷事件
{
case Q2: //在s1狀態
if(W1_event) //如果發生W1事件,那麼就執行E1動作,並將狀態轉移到Q1態;
{
Lifting_lever.raise();//執行E1動作;
nxt_state = Q1;
}
else
{
break;
}
case Q1: //在Q1狀態
if(W2_event) //如果發生W2事件,那麼就執行E2動作,並將狀態轉移到Q2;
{
Lifting_lever.down();//執行E2動作;
nxt_state = Q2;
}
else
{
break;
}
}
在http://kb.cnblogs.com/page/528972/上面瞭解到狀態機器的兩種寫法,橫寫和豎寫
橫豎兩種寫法的程式碼片段,實現的功能完全相同,但是,橫著寫的效果明顯好於豎著寫的效果。理由如下:
1、豎著寫隱含了優先順序排序(其實各個事件是同優先順序的),排在前面的事件判斷將毫無疑問地優先於排在後面的事件判斷。這種if/else if寫法上的限制將破壞事件間原有的關係。而橫著寫不存在此問題。
2、由於處在每個狀態時的事件數目不一致,而且事件發生的時間是隨機的,無法預先確定,導致豎著寫淪落為順序查詢方式,結構上的缺陷使得大量時間被浪費。對於橫著寫,在某個時間點,狀態是唯一確定的,在事件裡尋找狀態只要使用switch語句,能一步定位到相應的狀態,延遲時間可以預先準確估算。而且在事件發生時,呼叫事件函數,在函數裡尋找唯一確定的狀態,並根據其執行動作和狀態轉移的思路清晰簡潔, 效率高,富有美感。
這裡之所以使用豎著寫的方法,是因為這是個小項目,邏輯不太複雜,功能精簡,同時為了節約記憶體耗費,所以豎著寫的方法也不失為一種合適的選擇。
即時軟體控制第二周作業