首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 語言實作有限狀態機 (FSM) 完整教學:從理論到跳轉表驅動的工程級設計

     編輯:關於C

前言

有限狀態機 (Finite State Machine, FSM) 是軟體工程中處理複雜邏輯流程的利器。在嵌入式系統中,受限於記憶體與即時性要求,C 語言實作 FSM 通常採用 跳轉表 驅動,達到 O(1) 狀態轉換、無分支預測失誤、程式碼結構清晰的效果。本文從核心要素分析、資料結構設計、完整程式碼實作三個層面,帶你打造可擴充的嵌入式級 FSM 框架。

一、FSM 核心要素分析

一個 FSM 本質上包含三個核心概念:

  • 狀態:系統當前所處的模式 (如 IDLE, RUN, ERROR)。
  • 輸入/條件:觸發狀態變化的事件 (如 BTN_PRESS, TIMEOUT, MSG_RECV)。
  • 轉移/行為:<條件 + 當前狀態> → <下一狀態 + 執行動作> 的映射規則。

狀態轉移圖範例

狀態集合: {S1, S2, S3, STRAP}
條件集合: {C1, C2}

S1 --C1/A1--> S2
S2 --C2/A2--> S3
S3 --C1/A3--> S2
其他輸入   --> STRAP (陷阱狀態,不可逃脫)

對應真理表:

當前狀態輸入下一狀態動作
S1C1S2A1
S2C2S3A2
S3C1S2A3
任意其他STRAPATRAP

二、資料結構設計 (嵌入式優化版)

1. 基礎型別定義


typedef int State;
typedef int Condition;

#define STATES 4
#define STATE1 0
#define STATE2 1
#define STATE3 2
#define STATETRAP 3

#define CONDITIONS 2
#define CONDITION1 0
#define CONDITION2 1

2. 動作函式指標型別


typedef void (*ActionFunc)(State current, Condition cond);

3. 轉移結構體


typedef struct {
    State next;         // 下一狀態
    ActionFunc action;  // 執行動作
} Transition, *PTransition;

4. 定義具體轉移 (對應真理表)


// 動作函式實作 (此處僅列印)
void action1(State s, Condition c) { printf("Action 1 triggered\n"); }
void action2(State s, Condition c) { printf("Action 2 triggered\n"); }
void action3(State s, Condition c) { printf("Action 3 triggered\n"); }
void actionTrap(State s, Condition c) { printf("Trap action triggered\n"); }

// 轉移實例
Transition t1 = { STATE2, action1 };   // S1 + C1 -> S2, A1
Transition t2 = { STATE3, action2 };   // S2 + C2 -> S3, A2
Transition t3 = { STATE2, action3 };   // S3 + C1 -> S2, A3
Transition tt = { STATETRAP, actionTrap }; // 陷阱轉移

5. 跳轉表 (核心:O(1) 查找)


// 索引: [當前狀態][輸入條件]
PTransition transition_table[STATES][CONDITIONS] = {
    /*      C1          C2     */
    /* S1 */ &t1,        &tt,    // S1: C1->t1, C2->trap
    /* S2 */ &tt,        &t2,    // S2: C1->trap, C2->t2
    /* S3 */ &t3,        &tt,    // S3: C1->t3, C2->trap
    /* TR */ &tt,        &tt     // TRAP: 任何輸入留在陷阱
};

6. 狀態機結構體


typedef struct {
    State current;
} StateMachine, *PStateMachine;

7. 核心步進函式


State step(PStateMachine machine, Condition cond) {
    PTransition t = transition_table[machine->current][cond];
    (t->action)(machine->current, cond);  // 執行動作
    machine->current = t->next;           // 更新狀態
    printf("Current state: %d\n", machine->current);
    return machine->current;
}

三、完整可執行程式碼


#include <stdio.h>
#include <stdlib.h>

typedef int State;
typedef int Condition;

#define STATENUM 4
#define STATE1 0
#define STATE2 1
#define STATE3 2
#define STATETRAP 3

#define CONDITIONS 2
#define CONDITION1 0
#define CONDITION2 1

typedef void (*ActionFunc)(State, Condition);

typedef struct {
    State next;
    ActionFunc action;
} Transition, *PTransition;

// 動作函式宣告
void action1(State, Condition);
void action2(State, Condition);
void action3(State, Condition);
void actionTrap(State, Condition);

// 轉移定義
Transition t1 = { STATE2, action1 };
Transition t2 = { STATE3, action2 };
Transition t3 = { STATE2, action3 };
Transition tt = { STATETRAP, actionTrap };

// 跳轉表
PTransition transition_table[STATENUM][CONDITIONS] = {
    { &t1, &tt },
    { &tt, &t2 },
    { &t3, &tt },
    { &tt, &tt }
};

typedef struct { State current; } StateMachine, *PStateMachine;

State step(PStateMachine machine, Condition cond) {
    PTransition t = transition_table[machine->current][cond];
    (t->action)(machine->current, cond);
    machine->current = t->next;
    printf("Current state: %d\n", machine->current);
    return machine->current;
}

// 動作實作
void action1(State s, Condition c) { printf("Action 1 triggered\n"); }
void action2(State s, Condition c) { printf("Action 2 triggered\n"); }
void action3(State s, Condition c) { printf("Action 3 triggered\n"); }
void actionTrap(State s, Condition c) { printf("Trap action triggered\n"); }

int main() {
    StateMachine machine = { .current = STATE1 };
    int input;
    
    printf("FSM Demo: Enter 0 (C1) or 1 (C2), other to quit\n");
    while (scanf("%d", &input) == 1) {
        if (input < 0 || input >= CONDITIONS) break;
        step(&machine, input);
    }
    return 0;
}

四、執行範例


FSM Demo: Enter 0 (C1) or 1 (C2), other to quit
0
Action 1 triggered
Current state: 1
1
Action 2 triggered
Current state: 2
0
Action 3 triggered
Current state: 1
1
Trap action triggered
Current state: 3
0
Trap action triggered
Current state: 3

五、工程級擴充建議

需求擴充方案
多任務/重入支援狀態機結構體加入 mutex 或採用無鎖環狀緩衝區佇列事件
動態增減狀態跳轉表改為動態配置的二維陣列或雜湊表
狀態進入/離開動作擴充 Transition 結構加入 on_entry, on_exit 函式指標
層狀狀態機 (HSM)狀態結構體加入 parent 指標,步進函式遞迴處理
事件帶參數Condition 改為 void* 或聯合體,動作函式簽名調整
自動化生成用 Python/Excel 定義狀態表,腳本生成 C 碼,避免手寫錯誤

總結:跳轉表驅動的 FSM 是嵌入式系統的「黃金模式」——確定性執行時間、極低記憶體佔用、結構與邏輯分離、易於測試與維護。掌握此模式,即掌握了複雜控制邏輯的工程化鑰匙。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved