嵌入式設計模式:有限狀態自動機的c語言實現
狀態機模式是一種行為模式,在《設計模式》這本書中對其有詳細的描述,通過多型實現不同狀態的調轉行為的確是一種很好的方法,只可惜在嵌入式環境下,有時只能寫純c**,並且還需要考慮**的重入和多工請求跳轉等情形,因此實現起來著實需要一番考慮。
近日在看了乙個開源系統時,看到了乙個狀態機的實現,也學著寫了乙個,與大家分享。
首先,分析一下乙個普通的狀態機究竟要實現哪些內容。
狀態機儲存從開始時刻到現在的變化,並根據當前輸入,決定下乙個狀態。這意味著,狀態機要儲存狀態、獲得輸入(我們把它叫做跳轉條件)、做出響應。
如上圖所示,均為狀態,箭頭c1/a1表示在s1狀態、輸入為c1時,跳轉到s2,並進行a1操作。
最下方為一組輸入,狀態機應做出如下反應:
當前狀態
輸入下乙個狀態
動作s1
c1s2
a1s2
c2s3
a2s3
c1s2
a3s2
c2s3
a2s3
c1s2
a3s2
c1s_trap
a_trap
s_trap
c1s_trap
a_trap
當某個狀態遇到不能識別的輸入時,就預設進入陷阱狀態,在陷阱狀態中,不論遇到怎樣的輸入都不能跳出。
為了表達上面這個自動機,我們定義它們的狀態和輸入型別:
typedef
int
state;
typedef
int
condition;
#define states 3 + 1
#define state_1 0
#define state_2 1
#define state_3 2
#define state_trap 3
#define conditions 2
#define condition_1 0
#define condition_2 1
在嵌入式環境中,由於儲存空間比較小,因此把它們全部定義成巨集。此外,為了降低執行時間的不確定性,我們使用o(1)的跳轉表來模擬狀態的跳轉。
首先定義跳轉型別:
typedef
void
(*actiontype)(state state, condition condition);
typedef
struct
trasition, * ptrasition;
然後按照上圖中的跳轉關係,把三個跳轉加乙個陷阱跳轉先定義出來:
// (s1, c1, s2, a1)
trasition t1 = ;
// (s2, c2, s3, a2)
trasition t2 = ;
// (s3, c1, s2, a3)
trasition t3 = ;
// (s, c, trap, a1)
trasition tt = ;
其中的動作,由使用者自己完成,在這裡僅定義一條輸出語句。
void
action_1(state state, condition condition)
最後定義跳轉表:
ptrasition transition_table[states][conditions] = ;
即可表達上文中的跳轉關係。
最後定義狀態機,如果不考慮多工請求,那麼狀態機僅需要儲存當前狀態便行了。例如:
typedef
struct
statemachine, * pstatemachine;
state step(pstatemachine machine, condition condition)
但是考慮到當乙個跳轉正在進行的時候,同時又有其他任務請求跳轉,則會出現資料不一致的問題。
舉個例子:task1(s1, c1/a1 –> s2)和task2(s2, c2/a2 –> s3)先後執行,是可以順利到達s3狀態的,但若操作a1執行的時候,執行許可權被task2搶占,則task2此時看到的當前狀態還是s1,s1遇到c2就進入陷阱狀態,而不會到達s3了,也就是說,狀態的跳**生了不確定,這是不能容忍的。
因此要重新設計狀態機,增加乙個「事務中」條件和乙個用於儲存輸入的條件佇列。修改後的**如下:
#define e_ok 0
#define e_no_data 1
#define e_overflow 2
typedef
struct
conditionqueue, * pconditionqueue;
int
push(conditionqueue * queue, condition c)
else
return
e_ok;
}
int
poll(conditionqueue * queue, condition * c)
else
return
e_ok;
}
typedef
struct
statemachine, * pstatemachine;
static
state __step(pstatemachine machine, condition condition)
state step(pstatemachine machine, condition condition)
else
machine->intransaction =
false
;
return
current;
}
}
void
initialize(pstatemachine machine, state s)
**
有限狀態自動機
有限自動機是更一般化的狀態轉化圖。分為確定有限自動機 dfa 和不確定有限自動機 nfa m s,f,so,z 其中 下圖為乙個確定的有限狀態自動機 m s,f,so,z 其中 下圖為乙個不確定的有限狀態自動機 說了半天其實它們的本質區別就在於s0,確定的有限狀態自動機的s0是唯一確定的。而不確定的...
有限狀態自動機
有限自動機是更一般化的狀態轉化圖。分為確定有限自動機 dfa 和不確定有限自動機 nfa m s,f,so,z 其中 下圖為乙個確定的有限狀態自動機 m s,f,so,z 其中 下圖為乙個不確定的有限狀態自動機 說了半天其實它們的本質區別就在於s0,確定的有限狀態自動機的s0是唯一確定的。而不確定的...
有限狀態自動機
背景提要 星期三的時候,xw交給我乙個點燈的任務 大意是乙個玩意單擊的時候如何如何,長按又如何如何,雙擊又如何如何,幾種狀態分別執行不同的操作。這就導致了一種情況 在機器第一次檢測到按鈕被按下時,我們無法做出論斷 我們不知道這是一次雙擊還是長按還是單擊,我們只能靜觀其變,見機行事。但是按鈕被按下時,...