嵌入式設(shè)計(jì)模式:有限狀態(tài)自動(dòng)機(jī)的C語(yǔ)言實(shí)現(xiàn)
[導(dǎo)讀]星標(biāo)「嵌入式大雜燴」,一起進(jìn)步!來(lái)源:www.cnblogs.com/autosar/archive/2012/06/22/2558604.html狀態(tài)機(jī)模式是一種行為模式,在《設(shè)計(jì)模式》這本書中對(duì)其有詳細(xì)的描述,通過(guò)多態(tài)實(shí)現(xiàn)不同狀態(tài)的調(diào)轉(zhuǎn)行為的確是一種很好的方法,只可惜在嵌入式...
《設(shè)計(jì)模式》這本書中對(duì)其有詳細(xì)的描述,通過(guò)多態(tài)實(shí)現(xiàn)不同狀態(tài)的調(diào)轉(zhuǎn)行為的確是一種很好的方法,只可惜在嵌入式環(huán)境下,有時(shí)只能寫純C代碼,并且還需要考慮代碼的重入和多任務(wù)請(qǐng)求跳轉(zhuǎn)等情形,因此實(shí)現(xiàn)起來(lái)著實(shí)需要一番考慮。
近日在看了一個(gè)開(kāi)源系統(tǒng)時(shí),看到了一個(gè)狀態(tài)機(jī)的實(shí)現(xiàn),也學(xué)著寫了一個(gè),與大家分享。
首先,分析一下一個(gè)普通的狀態(tài)機(jī)究竟要實(shí)現(xiàn)哪些內(nèi)容。
狀態(tài)機(jī)存儲(chǔ)從開(kāi)始時(shí)刻到現(xiàn)在的變化,并根據(jù)當(dāng)前輸入,決定下一個(gè)狀態(tài)。這意味著,狀態(tài)機(jī)要存儲(chǔ)狀態(tài)、獲得輸入(我們把它叫做跳轉(zhuǎn)條件)、做出響應(yīng)。
如上圖所示,{s1, s2, s3}均為狀態(tài),箭頭c1/a1表示在s1狀態(tài)、輸入為c1時(shí),跳轉(zhuǎn)到s2,并進(jìn)行a1操作。
最下方為一組輸入,狀態(tài)機(jī)應(yīng)做出如下反應(yīng):
當(dāng)某個(gè)狀態(tài)遇到不能識(shí)別的輸入時(shí),就默認(rèn)進(jìn)入陷阱狀態(tài),在陷阱狀態(tài)中,不論遇到怎樣的輸入都不能跳出。
為了表達(dá)上面這個(gè)自動(dòng)機(jī),我們定義它們的狀態(tài)和輸入類型:
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
在嵌入式環(huán)境中,由于存儲(chǔ)空間比較小,因此把它們?nèi)慷x成宏。此外,為了降低執(zhí)行時(shí)間的不確定性,我們使用O(1)的跳轉(zhuǎn)表來(lái)模擬狀態(tài)的跳轉(zhuǎn)。
首先定義跳轉(zhuǎn)類型:
typedef void (*ActionType)(State state, Condition condition);
typedef struct
{
State next;
ActionType action;
} Trasition, * pTrasition;
然后按照上圖中的跳轉(zhuǎn)關(guān)系,把三個(gè)跳轉(zhuǎn)加一個(gè)陷阱跳轉(zhuǎn)先定義出來(lái):
// (s1, c1, s2, a1)
Trasition t1 = {
STATE_2,
action_1
};
// (s2, c2, s3, a2)
Trasition t2 = {
STATE_3,
action_2
};
// (s3, c1, s2, a3)
Trasition t3 = {
STATE_2,
action_3
};
// (s, c, trap, a1)
Trasition tt = {
STATE_TRAP,
action_trap
};
其中的動(dòng)作,由用戶自己完成,在這里僅定義一條輸出語(yǔ)句。
void action_1(State state, Condition condition)
{
printf("Action 1 triggered.\n");
}
最后定義跳轉(zhuǎn)表:
pTrasition transition_table[STATES][CONDITIONS] = {
/* c1, c2*/
/* s1 */ 




