UML之状态图学习

目录

  1. 状态图的本质理解
  2. 什么时候必须用状态图
  3. 状态图的核心元素详解
  4. 从需求到代码的完整流程
  5. 7个完整实战案例
  6. 高级特性:层次状态与并发
  7. 状态表与代码生成
  8. 调试与优化技巧
  9. PlantUML 绘制指南

一、状态图的本质理

核心定义

状态图 = switch-case 状态机的"上帝视角设计图"

你现在写的代码

c 复制代码
// 你可能这样写代码
switch(state) {
    case IDLE:
        // ...
        break;
    case RUN:
        // ...
        break;
    case ERROR:
        // ...
        break;
}

在 UML 里应该怎么做

复制代码
1. 先画状态图 → 理清状态和转换
2. 再写代码   → 一一对应,不会乱
3. 边调试     → 对照状态图检查

状态图的价值

维度 没有状态图 有状态图
设计阶段 边写边想,容易遗漏 全局视角,提前发现问题
开发阶段 if-else 嵌套地狱 清晰的 switch-case
调试阶段 不知道当前在哪个状态 一眼看出状态转换逻辑
维护阶段 要读完整代码才能理解 看图就知道系统行为
交接阶段 难以理解前人代码 图文结合,快速上手

二、什么时候"必须"用状态图?

判断标准

只要满足下面任意一条,就该画状态图:

复制代码
✅ 系统有多种运行模式
   例如:待机、运行、睡眠

✅ 行为依赖于当前状态
   例如:只有在"空闲"状态才能接收新任务

✅ 同一个事件,在不同状态下行为不同
   例如:按下按钮,在不同模式下响应不同

✅ 用 if/else 已经开始乱了
   例如:多层嵌套,看不清楚逻辑

✅ 需要记录"系统在干什么"
   例如:设备状态监控、日志记录

嵌入式中的典型场景

应用场景 为什么需要状态图
设备控制 初始化 → 就绪 → 运行 → 故障
通信协议 连接 → 握手 → 传输 → 断开
电源管理 正常 → 低功耗 → 睡眠 → 唤醒
用户界面 主菜单 → 子菜单 → 设置 → 返回
传感器采集 空闲 → 采样 → 滤波 → 上报
电机控制 停止 → 启动 → 加速 → 匀速 → 减速

👉 嵌入式项目 90% 都满足这些条件


三、状态图的核心元素详解

元素对照表

UML 元素 UML 含义 C 语言对应 图形表示
State 系统所处状态 enum 圆角矩形
Event 触发条件 标志位/消息 箭头上的标签
Transition 状态切换 state = XXX 箭头
Action 进入/退出动作 函数调用 entry: / exit:
Guard 转换条件 if (condition) [condition]
Initial State 初始状态 初始值 实心圆
Final State 终止状态 结束标记 圆圈内有实心圆

详细解释

1. State(状态)

定义:系统在某个时间段内的稳定行为模式

图形表示

复制代码
┌──────────────┐
│   状态名称    │
├──────────────┤
│ entry: 动作   │
│ do: 活动      │
│ exit: 动作    │
└──────────────┘

C 语言实现

c 复制代码
typedef enum {
    STATE_IDLE,
    STATE_RUN,
    STATE_ERROR
} SystemState_t;

SystemState_t currentState = STATE_IDLE;

判断标准

  • ✅ 是一段稳定的行为区间
  • ✅ 有明确的进入条件和退出条件
  • ❌ 不是瞬时的动作(如"发送数据"不是状态)
2. Event(事件)

定义:触发状态转换的外部或内部条件

常见形式

事件类型 示例 C 语言实现
外部信号 按键、传感器 if (key_pressed)
定时器 超时 if (timer_expired)
消息 RTOS队列 xQueueReceive()
中断 UART接收 HAL_UART_RxCpltCallback()
条件 阈值判断 if (temp > 50)

命名规范

c 复制代码
// 好的命名(动词形式)
btn_pressed
timeout_occurred
data_received
error_detected

// 不好的命名
btn         // 不清楚是什么事件
data        // 太抽象
error       // 是什么错误?
3. Transition(转换)

定义:从一个状态到另一个状态的变化

完整语法

复制代码
事件[守卫条件] / 动作

示例:
btn_pressed[count < 10] / count++

C 语言实现

c 复制代码
// 完整的转换逻辑
if (btn_pressed && count < 10) {  // 事件 + 守卫
    count++;                       // 动作
    currentState = STATE_RUN;      // 状态转换
}
4. Action(动作)

分类

动作类型 触发时机 UML 写法 C 实现
Entry 进入状态时执行一次 entry: Motor_Start() 首次进入时调用
Exit 离开状态时执行一次 exit: Motor_Stop() 转换前调用
Do 在状态内持续执行 do: ReadSensor() 每次循环都执行
Transition 状态转换时执行 event / Action() 转换时调用一次

实现模式

c 复制代码
// Entry/Exit 动作的标准实现
typedef enum {
    STATE_IDLE,
    STATE_RUN,
    STATE_ERROR
} State_t;

State_t currentState = STATE_IDLE;
State_t lastState = STATE_IDLE;

void StateMachine_Update(void) {
    // 检测状态变化
    if (currentState != lastState) {
        // Exit 动作(离开旧状态)
        switch (lastState) {
            case STATE_RUN:
                Motor_Stop();  // exit action
                break;
        }
        
        // Entry 动作(进入新状态)
        switch (currentState) {
            case STATE_RUN:
                Motor_Start();  // entry action
                break;
        }
        
        lastState = currentState;
    }
    
    // Do 动作(状态内活动)
    switch (currentState) {
        case STATE_RUN:
            ReadSensor();  // do activity
            break;
    }
}
5. Guard(守卫条件)

定义 :在方括号 [] 中的布尔条件,决定转换是否发生

示例

复制代码
event[temp > 100] → STATE_OVERHEAT
event[battery < 10%] → STATE_LOW_POWER

C 实现

c 复制代码
if (event_occurred && temp > 100) {
    currentState = STATE_OVERHEAT;
}

四、从需求到代码的完整流程

流程图

复制代码
需求分析 → 列出状态 → 确定事件 → 画状态图 → 编写代码 → 测试验证

完整示例:STM32 设备控制

🎯 需求描述

设计一个设备控制系统,要求:

  1. 上电后自动初始化
  2. 初始化完成后进入空闲状态
  3. 收到启动命令后开始运行
  4. 运行过程中如果检测到错误,进入错误状态
  5. 错误状态下收到复位命令,返回空闲状态
  6. 任何状态下收到关机命令,进入关机流程
步骤 1:列出所有状态
c 复制代码
typedef enum {
    STATE_INIT,      // 初始化状态
    STATE_IDLE,      // 空闲状态
    STATE_RUN,       // 运行状态
    STATE_ERROR,     // 错误状态
    STATE_SHUTDOWN   // 关机状态
} DeviceState_t;

状态划分原则

  • ✅ 每个状态都是一个稳定的行为区间
  • ✅ 状态之间有明确的边界
  • ✅ 状态数量合理(建议 3-7 个)
步骤 2:确定所有事件
c 复制代码
typedef enum {
    EVENT_NONE,
    EVENT_INIT_DONE,      // 初始化完成
    EVENT_START_CMD,      // 启动命令
    EVENT_STOP_CMD,       // 停止命令
    EVENT_ERROR,          // 错误检测
    EVENT_RESET_CMD,      // 复位命令
    EVENT_SHUTDOWN_CMD    // 关机命令
} DeviceEvent_t;
步骤 3:画 UML 状态图
复制代码
                 ●  (开始)
                 │
                 ▼
            ┌─────────┐
            │  INIT   │
            │─────────│
            │entry:   │
            │ HW_Init()│
            └────┬────┘
                 │ init_done
                 ▼
            ┌─────────┐
      ┌─────│  IDLE   │◄─────────┐
      │     │─────────│          │
      │     │entry:   │          │ reset_cmd
      │     │ LED_Off()│          │
      │     └────┬────┘          │
      │          │ start_cmd      │
      │          ▼                │
      │     ┌─────────┐          │
      │     │  RUN    │──────────┘
      │     │─────────│
      │     │entry:   │
      │     │ Motor_On()│
      │     │exit:    │
      │     │Motor_Off()│
      │     └────┬────┘
      │          │ error_detected
      │          ▼
      │     ┌─────────┐
      └────>│  ERROR  │
            │─────────│
            │entry:   │
            │ LED_Red()│
            └────┬────┘
                 │ shutdown_cmd
                 ▼
            ┌─────────┐
            │SHUTDOWN │
            │─────────│
            │entry:   │
            │ Cleanup()│
            └────┬────┘
                 │
                 ▼
                 ◉  (结束)
步骤 4:状态转换表(设计文档)
当前状态 事件 守卫条件 动作 下一状态
INIT init_done - - IDLE
IDLE start_cmd - - RUN
RUN stop_cmd - - IDLE
RUN error_detected - - ERROR
ERROR reset_cmd - - IDLE
* shutdown_cmd - Cleanup() SHUTDOWN

说明* 表示任何状态

步骤 5:编写 C 代码
5.1 状态机结构体
c 复制代码
typedef struct {
    DeviceState_t currentState;
    DeviceState_t lastState;
    DeviceEvent_t event;
    bool stateChanged;
} StateMachine_t;

static StateMachine_t sm = {
    .currentState = STATE_INIT,
    .lastState = STATE_INIT,
    .event = EVENT_NONE,
    .stateChanged = false
};
5.2 状态机核心函数
c 复制代码
void StateMachine_Update(void)
{
    // 1. 检测状态变化,执行 Entry/Exit 动作
    if (sm.currentState != sm.lastState) {
        // Exit 动作
        StateMachine_ExitAction(sm.lastState);
        
        // Entry 动作
        StateMachine_EntryAction(sm.currentState);
        
        sm.lastState = sm.currentState;
        sm.stateChanged = true;
    } else {
        sm.stateChanged = false;
    }
    
    // 2. 状态转换逻辑
    switch (sm.currentState)
    {
        case STATE_INIT:
            if (sm.event == EVENT_INIT_DONE) {
                sm.currentState = STATE_IDLE;
            }
            break;
            
        case STATE_IDLE:
            if (sm.event == EVENT_START_CMD) {
                sm.currentState = STATE_RUN;
            }
            break;
            
        case STATE_RUN:
            if (sm.event == EVENT_STOP_CMD) {
                sm.currentState = STATE_IDLE;
            }
            else if (sm.event == EVENT_ERROR) {
                sm.currentState = STATE_ERROR;
            }
            break;
            
        case STATE_ERROR:
            if (sm.event == EVENT_RESET_CMD) {
                sm.currentState = STATE_IDLE;
            }
            break;
            
        case STATE_SHUTDOWN:
            // 终止状态,不再转换
            break;
    }
    
    // 3. 全局转换(任何状态都响应)
    if (sm.event == EVENT_SHUTDOWN_CMD) {
        sm.currentState = STATE_SHUTDOWN;
    }
    
    // 4. 清除事件
    sm.event = EVENT_NONE;
    
    // 5. Do 动作(状态内活动)
    StateMachine_DoAction(sm.currentState);
}
5.3 Entry/Exit/Do 动作
c 复制代码
void StateMachine_EntryAction(DeviceState_t state)
{
    switch (state)
    {
        case STATE_INIT:
            printf("Entering INIT state\n");
            HW_Init();
            // 初始化完成后自动触发事件
            StateMachine_SendEvent(EVENT_INIT_DONE);
            break;
            
        case STATE_IDLE:
            printf("Entering IDLE state\n");
            LED_Off();
            break;
            
        case STATE_RUN:
            printf("Entering RUN state\n");
            Motor_Start();
            LED_Green();
            break;
            
        case STATE_ERROR:
            printf("Entering ERROR state\n");
            LED_Red();
            Buzzer_On();
            break;
            
        case STATE_SHUTDOWN:
            printf("Entering SHUTDOWN state\n");
            Cleanup();
            break;
    }
}

void StateMachine_ExitAction(DeviceState_t state)
{
    switch (state)
    {
        case STATE_RUN:
            printf("Exiting RUN state\n");
            Motor_Stop();
            break;
            
        case STATE_ERROR:
            printf("Exiting ERROR state\n");
            Buzzer_Off();
            break;
            
        default:
            // 其他状态没有特殊的退出动作
            break;
    }
}

void StateMachine_DoAction(DeviceState_t state)
{
    switch (state)
    {
        case STATE_RUN:
            // 运行状态下持续监测
            if (CheckError()) {
                StateMachine_SendEvent(EVENT_ERROR);
            }
            UpdateSensors();
            break;
            
        case STATE_ERROR:
            // 错误状态下闪烁LED
            LED_Toggle();
            break;
            
        default:
            break;
    }
}
5.4 事件发送接口
c 复制代码
void StateMachine_SendEvent(DeviceEvent_t event)
{
    sm.event = event;
}

DeviceState_t StateMachine_GetCurrentState(void)
{
    return sm.currentState;
}

const char* StateMachine_GetStateName(DeviceState_t state)
{
    switch (state) {
        case STATE_INIT:     return "INIT";
        case STATE_IDLE:     return "IDLE";
        case STATE_RUN:      return "RUN";
        case STATE_ERROR:    return "ERROR";
        case STATE_SHUTDOWN: return "SHUTDOWN";
        default:             return "UNKNOWN";
    }
}
5.5 主循环使用
c 复制代码
int main(void)
{
    HAL_Init();
    
    while (1)
    {
        // 1. 更新状态机
        StateMachine_Update();
        
        // 2. 处理外部输入
        if (Button_Pressed()) {
            StateMachine_SendEvent(EVENT_START_CMD);
        }
        
        // 3. 延时
        HAL_Delay(10);
    }
}
PlantUML 代码
plantuml 复制代码
@startuml DeviceStateMachine

[*] --> INIT

state INIT {
    INIT : entry: HW_Init()
}

state IDLE {
    IDLE : entry: LED_Off()
}

state RUN {
    RUN : entry: Motor_Start()
    RUN : do: UpdateSensors()
    RUN : exit: Motor_Stop()
}

state ERROR {
    ERROR : entry: LED_Red()
    ERROR : entry: Buzzer_On()
    ERROR : exit: Buzzer_Off()
}

state SHUTDOWN {
    SHUTDOWN : entry: Cleanup()
}

INIT --> IDLE : init_done
IDLE --> RUN : start_cmd
RUN --> IDLE : stop_cmd
RUN --> ERROR : error_detected
ERROR --> IDLE : reset_cmd

INIT --> SHUTDOWN : shutdown_cmd
IDLE --> SHUTDOWN : shutdown_cmd
RUN --> SHUTDOWN : shutdown_cmd
ERROR --> SHUTDOWN : shutdown_cmd

SHUTDOWN --> [*]

@enduml

五、完整实战案例

案例 1:电机控制器状态机

需求描述
  • 电机有停止、启动、加速、匀速、减速五个状态
  • 启动后经过加速阶段进入匀速运行
  • 收到停止命令后经过减速阶段才停止
  • 任何状态下检测到过流立即停止
状态图
复制代码
                 ●
                 │
                 ▼
            ┌────────┐
            │  STOP  │◄──────────┐
            │────────│           │
            │speed=0 │           │ overcurrent
            └───┬────┘           │
                │ start_cmd       │
                ▼                 │
            ┌────────┐           │
            │  START │           │
            │────────│           │
            │speed++ │           │
            └───┬────┘           │
                │ speed>=min      │
                ▼                 │
            ┌────────┐           │
            │  ACCEL │           │
            │────────│           │
            │speed++ │           │
            └───┬────┘           │
                │ speed>=target   │
                ▼                 │
            ┌────────┐           │
            │  STEADY│───────────┤
            │────────│           │
            │speed=target        │
            └───┬────┘           │
                │ stop_cmd        │
                ▼                 │
            ┌────────┐           │
            │  DECEL │           │
            │────────│           │
            │speed-- │           │
            └───┬────┘           │
                │ speed<=0        │
                └─────────────────┘
代码实现
c 复制代码
typedef enum {
    MOTOR_STOP,
    MOTOR_START,
    MOTOR_ACCEL,
    MOTOR_STEADY,
    MOTOR_DECEL
} MotorState_t;

typedef struct {
    MotorState_t state;
    uint16_t speed;
    uint16_t targetSpeed;
    bool startCmd;
    bool stopCmd;
    bool overcurrent;
} MotorController_t;

static MotorController_t motor = {
    .state = MOTOR_STOP,
    .speed = 0,
    .targetSpeed = 1000,
    .startCmd = false,
    .stopCmd = false,
    .overcurrent = false
};

void MotorController_Update(void)
{
    // 全局紧急停止
    if (motor.overcurrent) {
        motor.speed = 0;
        motor.state = MOTOR_STOP;
        Motor_SetSpeed(0);
        return;
    }
    
    switch (motor.state)
    {
        case MOTOR_STOP:
            motor.speed = 0;
            Motor_SetSpeed(0);
            
            if (motor.startCmd) {
                motor.startCmd = false;
                motor.state = MOTOR_START;
            }
            break;
            
        case MOTOR_START:
            motor.speed += 10;  // 启动加速度
            Motor_SetSpeed(motor.speed);
            
            if (motor.speed >= 100) {  // 最小稳定速度
                motor.state = MOTOR_ACCEL;
            }
            break;
            
        case MOTOR_ACCEL:
            if (motor.speed < motor.targetSpeed) {
                motor.speed += 5;  // 加速度
                Motor_SetSpeed(motor.speed);
            }
            
            if (motor.speed >= motor.targetSpeed) {
                motor.state = MOTOR_STEADY;
            }
            
            if (motor.stopCmd) {
                motor.stopCmd = false;
                motor.state = MOTOR_DECEL;
            }
            break;
            
        case MOTOR_STEADY:
            motor.speed = motor.targetSpeed;
            Motor_SetSpeed(motor.speed);
            
            if (motor.stopCmd) {
                motor.stopCmd = false;
                motor.state = MOTOR_DECEL;
            }
            break;
            
        case MOTOR_DECEL:
            if (motor.speed > 0) {
                motor.speed -= 10;  // 减速度
                if (motor.speed < 10) {
                    motor.speed = 0;
                }
                Motor_SetSpeed(motor.speed);
            }
            
            if (motor.speed == 0) {
                motor.state = MOTOR_STOP;
            }
            break;
    }
}

案例 2:TCP 连接状态机(协议栈)

状态图
复制代码
                 ●
                 │
                 ▼
            ┌────────┐
            │ CLOSED │
            └───┬────┘
                │ open
                ▼
            ┌────────┐
            │ LISTEN │
            └───┬────┘
                │ syn_received
                ▼
            ┌────────┐
            │SYN_RCVD│
            └───┬────┘
                │ ack_received
                ▼
            ┌────────┐
            │ESTABLISH│
            └───┬────┘
                │ close / fin_received
                ▼
            ┌────────┐
            │FIN_WAIT│
            └───┬────┘
                │ ack_received
                ▼
            ┌────────┐
            │ CLOSED │
            └────────┘
代码实现
c 复制代码
typedef enum {
    TCP_CLOSED,
    TCP_LISTEN,
    TCP_SYN_RCVD,
    TCP_ESTABLISHED,
    TCP_FIN_WAIT,
    TCP_CLOSING,
    TCP_TIME_WAIT
} TcpState_t;

typedef struct {
    TcpState_t state;
    uint32_t timeout;
} TcpConnection_t;

void TCP_StateMachine(TcpConnection_t *conn, TcpEvent_t event)
{
    switch (conn->state)
    {
        case TCP_CLOSED:
            if (event == TCP_EVENT_OPEN) {
                conn->state = TCP_LISTEN;
            }
            break;
            
        case TCP_LISTEN:
            if (event == TCP_EVENT_SYN_RECEIVED) {
                TCP_SendSynAck();
                conn->state = TCP_SYN_RCVD;
            }
            break;
            
        case TCP_SYN_RCVD:
            if (event == TCP_EVENT_ACK_RECEIVED) {
                conn->state = TCP_ESTABLISHED;
            }
            else if (event == TCP_EVENT_TIMEOUT) {
                conn->state = TCP_CLOSED;
            }
            break;
            
        case TCP_ESTABLISHED:
            if (event == TCP_EVENT_CLOSE) {
                TCP_SendFin();
                conn->state = TCP_FIN_WAIT;
            }
            else if (event == TCP_EVENT_FIN_RECEIVED) {
                TCP_SendAck();
                conn->state = TCP_CLOSING;
            }
            break;
            
        case TCP_FIN_WAIT:
            if (event == TCP_EVENT_ACK_RECEIVED) {
                conn->state = TCP_CLOSED;
            }
            break;
            
        case TCP_CLOSING:
            if (event == TCP_EVENT_ACK_RECEIVED) {
                conn->state = TCP_TIME_WAIT;
                conn->timeout = GetTick() + 2000; // 2秒超时
            }
            break;
            
        case TCP_TIME_WAIT:
            if (GetTick() >= conn->timeout) {
                conn->state = TCP_CLOSED;
            }
            break;
    }
}

案例 3:按键状态机(防抖 + 长按检测)

需求描述
  • 检测按键按下、释放
  • 防抖处理
  • 区分短按和长按
状态图
复制代码
            ┌────────┐
        ┌──>│ IDLE   │
        │   └───┬────┘
        │       │ key_down
        │       ▼
        │   ┌────────┐
        │   │DEBOUNCE│
        │   └───┬────┘
        │       │ timer > 50ms
        │       ▼
        │   ┌────────┐
        │   │PRESSED │
        │   └───┬────┘
        │       │ timer > 1000ms
        │       ▼
        │   ┌────────┐
        │   │LONGPRESS
        │   └───┬────┘
        │       │ key_up
        │       ▼
        │   ┌────────┐
        └───│RELEASED│
            └────────┘
代码实现
c 复制代码
typedef enum {
    KEY_IDLE,
    KEY_DEBOUNCE,
    KEY_PRESSED,
    KEY_LONG_PRESS,
    KEY_RELEASED
} KeyState_t;

typedef struct {
    KeyState_t state;
    uint32_t pressTime;
    bool shortPressDetected;
    bool longPressDetected;
} KeyStateMachine_t;

static KeyStateMachine_t key = {
    .state = KEY_IDLE,
    .pressTime = 0,
    .shortPressDetected = false,
    .longPressDetected = false
};

void Key_StateMachine_Update(void)
{
    bool keyDown = HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET;
    uint32_t currentTime = HAL_GetTick();
    
    switch (key.state)
    {
        case KEY_IDLE:
            if (keyDown) {
                key.pressTime = currentTime;
                key.state = KEY_DEBOUNCE;
            }
            break;
            
        case KEY_DEBOUNCE:
            if (!keyDown) {
                // 抖动,回到空闲
                key.state = KEY_IDLE;
            }
            else if (currentTime - key.pressTime > 50) {
                // 防抖时间到,确认按下
                key.state = KEY_PRESSED;
            }
            break;
            
        case KEY_PRESSED:
            if (!keyDown) {
                // 短按
                key.shortPressDetected = true;
                key.state = KEY_RELEASED;
            }
            else if (currentTime - key.pressTime > 1000) {
                // 长按阈值
                key.state = KEY_LONG_PRESS;
            }
            break;
            
        case KEY_LONG_PRESS:
            if (!keyDown) {
                // 长按释放
                key.longPressDetected = true;
                key.state = KEY_RELEASED;
            }
            // 可以在这里持续触发长按事件
            break;
            
        case KEY_RELEASED:
            // 等待按键完全释放
            if (!keyDown) {
                key.state = KEY_IDLE;
            }
            break;
    }
}

bool Key_IsShortPressed(void)
{
    if (key.shortPressDetected) {
        key.shortPressDetected = false;
        return true;
    }
    return false;
}

bool Key_IsLongPressed(void)
{
    if (key.longPressDetected) {
        key.longPressDetected = false;
        return true;
    }
    return false;
}

案例 4:菜单系统状态机(层次状态)

状态图
复制代码
                ┌──────────────────┐
                │   MENU_SYSTEM    │
                └────────┬─────────┘
                         │
        ┌────────────────┼────────────────┐
        │                │                │
        ▼                ▼                ▼
    ┌────────┐      ┌────────┐      ┌────────┐
    │ MAIN   │      │SETTINGS│      │  INFO  │
    │        │      │        │      │        │
    └────┬───┘      └────┬───┘      └────────┘
         │               │
         │               └──────┬─────────┐
         ▼                      ▼         ▼
    ┌────────┐           ┌──────────┐ ┌──────────┐
    │  RUN   │           │ DATETIME │ │  ALARM   │
    └────────┘           └──────────┘ └──────────┘
代码实现(层次状态机)
c 复制代码
typedef enum {
    MENU_MAIN,
    MENU_RUN,
    MENU_SETTINGS,
    MENU_DATETIME,
    MENU_ALARM,
    MENU_INFO
} MenuState_t;

typedef struct {
    MenuState_t current;
    MenuState_t parent;
    uint8_t selectedItem;
} MenuStateMachine_t;

static MenuStateMachine_t menu = {
    .current = MENU_MAIN,
    .parent = MENU_MAIN,
    .selectedItem = 0
};

void Menu_StateMachine(MenuEvent_t event)
{
    switch (menu.current)
    {
        case MENU_MAIN:
            if (event == EVENT_SELECT) {
                switch (menu.selectedItem) {
                    case 0:
                        menu.current = MENU_RUN;
                        menu.parent = MENU_MAIN;
                        break;
                    case 1:
                        menu.current = MENU_SETTINGS;
                        menu.parent = MENU_MAIN;
                        break;
                    case 2:
                        menu.current = MENU_INFO;
                        menu.parent = MENU_MAIN;
                        break;
                }
            }
            else if (event == EVENT_UP) {
                menu.selectedItem = (menu.selectedItem > 0) ? 
                    menu.selectedItem - 1 : 2;
            }
            else if (event == EVENT_DOWN) {
                menu.selectedItem = (menu.selectedItem < 2) ? 
                    menu.selectedItem + 1 : 0;
            }
            break;
            
        case MENU_SETTINGS:
            if (event == EVENT_SELECT) {
                switch (menu.selectedItem) {
                    case 0:
                        menu.current = MENU_DATETIME;
                        menu.parent = MENU_SETTINGS;
                        break;
                    case 1:
                        menu.current = MENU_ALARM;
                        menu.parent = MENU_SETTINGS;
                        break;
                }
            }
            else if (event == EVENT_BACK) {
                menu.current = menu.parent;
            }
            break;
            
        case MENU_DATETIME:
        case MENU_ALARM:
        case MENU_INFO:
            if (event == EVENT_BACK) {
                menu.current = menu.parent;
            }
            break;
            
        case MENU_RUN:
            if (event == EVENT_BACK) {
                menu.current = MENU_MAIN;
            }
            break;
    }
}

案例 5:洗衣机控制器

需求描述
  • 开机 → 选择模式 → 启动 → 洗涤 → 漂洗 → 脱水 → 完成
  • 任何阶段可以暂停/恢复
  • 开门时强制暂停
状态图
复制代码
        ●
        │
        ▼
    ┌────────┐
    │ READY  │
    └───┬────┘
        │ start
        ▼
    ┌────────┐
    │  WASH  │◄─────┐
    └───┬────┘      │
        │ timeout    │ resume
        ▼           │
    ┌────────┐      │
    │ RINSE  │      │
    └───┬────┘      │
        │ timeout    │
        ▼           │
    ┌────────┐      │
    │  SPIN  │      │
    └───┬────┘      │
        │ timeout    │
        ▼           │
    ┌────────┐      │
    │  DONE  │      │
    └────────┘      │
        │           │
        │ pause / door_open
        ▼           │
    ┌────────┐      │
    │ PAUSE  │──────┘
    └────────┘
代码实现
c 复制代码
typedef enum {
    WM_READY,
    WM_WASH,
    WM_RINSE,
    WM_SPIN,
    WM_PAUSE,
    WM_DONE
} WashingMachineState_t;

typedef struct {
    WashingMachineState_t state;
    WashingMachineState_t stateBeforePause;
    uint32_t timer;
    bool doorOpen;
} WashingMachine_t;

static WashingMachine_t wm = {
    .state = WM_READY,
    .stateBeforePause = WM_READY,
    .timer = 0,
    .doorOpen = false
};

void WashingMachine_Update(void)
{
    uint32_t currentTime = HAL_GetTick();
    
    // 全局条件:门打开时强制暂停
    if (wm.doorOpen && wm.state != WM_PAUSE && wm.state != WM_READY) {
        wm.stateBeforePause = wm.state;
        wm.state = WM_PAUSE;
        Motor_Stop();
        return;
    }
    
    switch (wm.state)
    {
        case WM_READY:
            if (GetStartButton() && !wm.doorOpen) {
                wm.state = WM_WASH;
                wm.timer = currentTime;
                Motor_Start(MOTOR_WASH_SPEED);
                Valve_Open();
            }
            break;
            
        case WM_WASH:
            if (currentTime - wm.timer > 10000) {  // 10秒洗涤
                wm.state = WM_RINSE;
                wm.timer = currentTime;
                Valve_Close();
                Pump_On();  // 排水
            }
            break;
            
        case WM_RINSE:
            if (currentTime - wm.timer > 5000) {  // 5秒漂洗
                wm.state = WM_SPIN;
                wm.timer = currentTime;
                Pump_Off();
                Motor_Start(MOTOR_SPIN_SPEED);
            }
            break;
            
        case WM_SPIN:
            if (currentTime - wm.timer > 5000) {  // 5秒脱水
                wm.state = WM_DONE;
                Motor_Stop();
                Buzzer_Beep();
            }
            break;
            
        case WM_PAUSE:
            Motor_Stop();
            if (GetResumeButton() && !wm.doorOpen) {
                wm.state = wm.stateBeforePause;
                wm.timer = currentTime;  // 重置定时器
                
                // 恢复对应状态的硬件
                switch (wm.state) {
                    case WM_WASH:
                        Motor_Start(MOTOR_WASH_SPEED);
                        break;
                    case WM_SPIN:
                        Motor_Start(MOTOR_SPIN_SPEED);
                        break;
                    default:
                        break;
                }
            }
            break;
            
        case WM_DONE:
            if (GetResetButton()) {
                wm.state = WM_READY;
            }
            break;
    }
}

案例 6:UART 接收状态机(协议解析)

场景描述

接收格式:[STX][LEN][DATA...][CHK][ETX]

  • STX = 0x02 (起始符)
  • LEN = 数据长度
  • DATA = 实际数据
  • CHK = 校验和
  • ETX = 0x03 (结束符)
状态图
复制代码
    ┌────────┐
    │ IDLE   │←────────────┐
    └───┬────┘             │
        │ rx == STX         │ error / timeout
        ▼                   │
    ┌────────┐             │
    │ LEN    │─────────────┤
    └───┬────┘             │
        │ rx byte           │
        ▼                   │
    ┌────────┐             │
    │ DATA   │─────────────┤
    └───┬────┘             │
        │ count == len      │
        ▼                   │
    ┌────────┐             │
    │ CHK    │─────────────┤
    └───┬────┘             │
        │ rx byte           │
        ▼                   │
    ┌────────┐             │
    │ ETX    │─────────────┤
    └───┬────┘             │
        │ rx == ETX         │
        ▼                   │
    ┌────────┐             │
    │ DONE   │─────────────┘
    └────────┘
代码实现
c 复制代码
typedef enum {
    UART_RX_IDLE,
    UART_RX_LEN,
    UART_RX_DATA,
    UART_RX_CHK,
    UART_RX_ETX,
    UART_RX_DONE,
    UART_RX_ERROR
} UartRxState_t;

#define STX 0x02
#define ETX 0x03
#define MAX_DATA_LEN 128

typedef struct {
    UartRxState_t state;
    uint8_t buffer[MAX_DATA_LEN];
    uint8_t length;
    uint8_t index;
    uint8_t checksum;
    uint32_t timeout;
} UartRxStateMachine_t;

static UartRxStateMachine_t uart = {
    .state = UART_RX_IDLE,
    .length = 0,
    .index = 0,
    .checksum = 0,
    .timeout = 0
};

void UART_RxStateMachine(uint8_t rxByte)
{
    uint32_t currentTime = HAL_GetTick();
    
    // 超时检测
    if (uart.state != UART_RX_IDLE && 
        currentTime - uart.timeout > 1000) {
        uart.state = UART_RX_ERROR;
        return;
    }
    
    switch (uart.state)
    {
        case UART_RX_IDLE:
            if (rxByte == STX) {
                uart.state = UART_RX_LEN;
                uart.index = 0;
                uart.checksum = 0;
                uart.timeout = currentTime;
            }
            break;
            
        case UART_RX_LEN:
            uart.length = rxByte;
            if (uart.length > 0 && uart.length <= MAX_DATA_LEN) {
                uart.state = UART_RX_DATA;
                uart.checksum += rxByte;
            } else {
                uart.state = UART_RX_ERROR;
            }
            break;
            
        case UART_RX_DATA:
            uart.buffer[uart.index++] = rxByte;
            uart.checksum += rxByte;
            
            if (uart.index >= uart.length) {
                uart.state = UART_RX_CHK;
            }
            break;
            
        case UART_RX_CHK:
            if (rxByte == uart.checksum) {
                uart.state = UART_RX_ETX;
            } else {
                uart.state = UART_RX_ERROR;
            }
            break;
            
        case UART_RX_ETX:
            if (rxByte == ETX) {
                uart.state = UART_RX_DONE;
                // 处理接收到的完整数据包
                ProcessReceivedData(uart.buffer, uart.length);
            } else {
                uart.state = UART_RX_ERROR;
            }
            break;
            
        case UART_RX_DONE:
        case UART_RX_ERROR:
            // 重置状态机
            uart.state = UART_RX_IDLE;
            break;
    }
}

案例 7:电源管理状态机(低功耗设计)

需求描述
  • 正常运行
  • 空闲一段时间后进入低功耗模式
  • 有活动时唤醒
  • 电池低电量时进入深度睡眠
状态图
复制代码
    ┌────────┐
    │ NORMAL │◄───────────┐
    └───┬────┘            │
        │ idle_timeout     │ activity
        ▼                 │
    ┌────────┐            │
    │ IDLE   │────────────┘
    └───┬────┘
        │ sleep_timeout
        ▼
    ┌────────┐
    │ SLEEP  │◄───────────┐
    └───┬────┘            │
        │ wakeup           │
        └─────────────────┘
        │ battery_low
        ▼
    ┌────────┐
    │DEEP_SLEEP
    └────────┘
代码实现
c 复制代码
typedef enum {
    PWR_NORMAL,
    PWR_IDLE,
    PWR_SLEEP,
    PWR_DEEP_SLEEP
} PowerState_t;

typedef struct {
    PowerState_t state;
    uint32_t lastActivity;
    uint16_t batteryLevel;
} PowerManagement_t;

static PowerManagement_t pwr = {
    .state = PWR_NORMAL,
    .lastActivity = 0,
    .batteryLevel = 100
};

#define IDLE_TIMEOUT     10000  // 10秒无活动进入IDLE
#define SLEEP_TIMEOUT    30000  // 30秒无活动进入SLEEP
#define LOW_BATTERY_THRESHOLD 10

void PowerManagement_Update(void)
{
    uint32_t currentTime = HAL_GetTick();
    uint32_t idleTime = currentTime - pwr.lastActivity;
    
    // 读取电池电量
    pwr.batteryLevel = ReadBatteryLevel();
    
    // 电池低电量强制深度睡眠
    if (pwr.batteryLevel < LOW_BATTERY_THRESHOLD) {
        if (pwr.state != PWR_DEEP_SLEEP) {
            PowerManagement_EnterDeepSleep();
            pwr.state = PWR_DEEP_SLEEP;
        }
        return;
    }
    
    switch (pwr.state)
    {
        case PWR_NORMAL:
            // 正常运行
            UpdateDisplay();
            ProcessSensors();
            
            if (idleTime > IDLE_TIMEOUT) {
                pwr.state = PWR_IDLE;
                // Entry action
                Display_Dim();
                ReduceCPU_Frequency();
            }
            break;
            
        case PWR_IDLE:
            // 降低功耗模式
            if (idleTime > SLEEP_TIMEOUT) {
                pwr.state = PWR_SLEEP;
                // Entry action
                Display_Off();
                DisablePeripherals();
                EnterSleepMode();
            }
            
            // 有活动时唤醒
            if (DetectActivity()) {
                pwr.state = PWR_NORMAL;
                pwr.lastActivity = currentTime;
                // Entry action
                Display_Bright();
                RestoreCPU_Frequency();
            }
            break;
            
        case PWR_SLEEP:
            // 睡眠模式(等待中断唤醒)
            // 这里通常由中断唤醒
            break;
            
        case PWR_DEEP_SLEEP:
            // 深度睡眠模式
            // 只能通过复位或特定外部事件唤醒
            break;
    }
}

void PowerManagement_OnActivity(void)
{
    pwr.lastActivity = HAL_GetTick();
    
    if (pwr.state == PWR_SLEEP) {
        // 从睡眠唤醒
        ExitSleepMode();
        EnablePeripherals();
        Display_On();
        pwr.state = PWR_NORMAL;
    }
    else if (pwr.state == PWR_IDLE) {
        pwr.state = PWR_NORMAL;
    }
}

// 中断回调中调用
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == WAKEUP_PIN) {
        PowerManagement_OnActivity();
    }
}

六、高级特性:层次状态与并发

层次状态(Hierarchical State)

概念

定义:一个状态可以包含子状态,形成状态的层次结构。

优势

  • 减少状态转换数量
  • 复用公共转换
  • 提高可维护性
示例:RUN 状态的层次结构
复制代码
┌────────── RUN ─────────────┐
│                            │
│  ┌──────┐    ┌──────┐     │
│  │IDLE  │───>│WORK  │     │
│  └──────┘    └──┬───┘     │
│                 │          │
│                 ▼          │
│              ┌──────┐      │
│              │PAUSE │      │
│              └──────┘      │
│                            │
└────────────────────────────┘
        │ stop
        ▼
    ┌──────┐
    │STOP  │
    └──────┘

特点

  • 在 RUN 的任何子状态下,收到 stop 事件都会退出到 STOP
  • 不需要为每个子状态都画到 STOP 的转换
代码实现
c 复制代码
typedef enum {
    STATE_STOP,
    STATE_RUN,
    STATE_RUN_IDLE,
    STATE_RUN_WORK,
    STATE_RUN_PAUSE
} HierarchicalState_t;

typedef struct {
    HierarchicalState_t state;
    HierarchicalState_t parent;
} StateMachine_t;

void StateMachine_Update(StateMachine_t *sm, Event_t event)
{
    // 先检查父状态的转换
    if (sm->parent == STATE_RUN) {
        if (event == EVENT_STOP) {
            sm->state = STATE_STOP;
            sm->parent = STATE_STOP;
            return;
        }
    }
    
    // 再检查当前状态的转换
    switch (sm->state)
    {
        case STATE_RUN_IDLE:
            if (event == EVENT_START) {
                sm->state = STATE_RUN_WORK;
            }
            break;
            
        case STATE_RUN_WORK:
            if (event == EVENT_PAUSE) {
                sm->state = STATE_RUN_PAUSE;
            }
            break;
            
        case STATE_RUN_PAUSE:
            if (event == EVENT_RESUME) {
                sm->state = STATE_RUN_WORK;
            }
            break;
    }
}

并发状态(Concurrent States)

概念

定义:系统同时处于多个正交的状态。

适用场景

  • 多任务系统
  • 独立的子系统
  • 并行的行为
示例:智能手机状态
复制代码
┌─────────────────────────────┐
│     Smartphone System       │
├─────────────┬───────────────┤
│             │               │
│  Screen     │   Network     │
│  ┌────┐     │   ┌────┐      │
│  │On  │     │   │WiFi│      │
│  └────┘     │   └────┘      │
│  ┌────┐     │   ┌────┐      │
│  │Off │     │   │4G  │      │
│  └────┘     │   └────┘      │
│             │   ┌────┐      │
│             │   │Off │      │
│             │   └────┘      │
└─────────────┴───────────────┘

特点

  • 屏幕状态和网络状态独立
  • 屏幕可以是 On,同时网络是 WiFi
  • 两个维度互不影响
PlantUML 代码
plantuml 复制代码
@startuml ConcurrentStates

state SmartphoneSystem {
  state Screen {
    state On
    state Off
    On --> Off : timeout
    Off --> On : touch
  }
  --
  state Network {
    state WiFi
    state FourG
    state Offline
    WiFi --> FourG : weak_signal
    FourG --> Offline : no_signal
    Offline --> WiFi : signal_restored
  }
}

@enduml

七、状态表与代码生成

状态转换表

当前状态 事件 守卫条件 动作 下一状态
IDLE start - Motor_On() RUN
RUN stop - Motor_Off() IDLE
RUN error temp > 80 Alarm_On() ERROR
ERROR reset - Alarm_Off() IDLE
* emergency - EmergencyStop() ERROR

基于表驱动的状态机

c 复制代码
typedef void (*ActionFunc)(void);
typedef bool (*GuardFunc)(void);

typedef struct {
    State_t currentState;
    Event_t event;
    GuardFunc guard;
    ActionFunc action;
    State_t nextState;
} StateTransition_t;

// 状态转换表
const StateTransition_t transitionTable[] = {
    {STATE_IDLE,  EVENT_START, NULL,         Motor_On,       STATE_RUN},
    {STATE_RUN,   EVENT_STOP,  NULL,         Motor_Off,      STATE_IDLE},
    {STATE_RUN,   EVENT_ERROR, CheckOverTemp, Alarm_On,       STATE_ERROR},
    {STATE_ERROR, EVENT_RESET, NULL,         Alarm_Off,      STATE_IDLE},
    // 通配符状态
    {STATE_ANY,   EVENT_EMERGENCY, NULL,     EmergencyStop,  STATE_ERROR},
};

#define TRANSITION_COUNT (sizeof(transitionTable) / sizeof(StateTransition_t))

void StateMachine_Process(State_t *state, Event_t event)
{
    for (int i = 0; i < TRANSITION_COUNT; i++)
    {
        const StateTransition_t *trans = &transitionTable[i];
        
        // 检查状态匹配
        if (trans->currentState != *state && trans->currentState != STATE_ANY) {
            continue;
        }
        
        // 检查事件匹配
        if (trans->event != event) {
            continue;
        }
        
        // 检查守卫条件
        if (trans->guard != NULL && !trans->guard()) {
            continue;
        }
        
        // 执行动作
        if (trans->action != NULL) {
            trans->action();
        }
        
        // 状态转换
        *state = trans->nextState;
        break;
    }
}

八、状态机的常见6个坑(避坑指南)

❌ 错误 1:把"动作"当"状态"

c 复制代码
// 错误示例
typedef enum {
    STATE_IDLE,
    STATE_SENDING_DATA,  // ❌ 这是动作,不是状态
    STATE_RECEIVING_DATA // ❌ 这是动作,不是状态
} State_t;

// 正确示例
typedef enum {
    STATE_IDLE,
    STATE_CONNECTED,     // ✅ 这是状态
    STATE_DISCONNECTED   // ✅ 这是状态
} State_t;

// 发送和接收是 CONNECTED 状态下的活动

判断标准

  • 状态 = 稳定的行为区间
  • 动作 = 瞬时的操作

❌ 错误 2:状态过多(>7 个)

c 复制代码
// 错误示例:状态太多
typedef enum {
    STATE_INIT,
    STATE_CHECK_CONFIG,
    STATE_LOAD_DATA,
    STATE_VERIFY_DATA,
    STATE_PROCESS_STEP1,
    STATE_PROCESS_STEP2,
    STATE_PROCESS_STEP3,
    STATE_SAVE_RESULT,
    STATE_CLEANUP,
    STATE_DONE,
    STATE_ERROR1,
    STATE_ERROR2,
    STATE_ERROR3
} State_t;  // ❌ 太多了!

// 正确示例:合并相似状态
typedef enum {
    STATE_INIT,
    STATE_PROCESS,  // ✅ 合并多个处理步骤
    STATE_DONE,
    STATE_ERROR
} State_t;

// 使用子状态或步骤变量
typedef enum {
    PROCESS_STEP1,
    PROCESS_STEP2,
    PROCESS_STEP3
} ProcessStep_t;

原则

  • 主状态不超过 7 个
  • 使用层次状态分解复杂逻辑
  • 使用步骤变量而不是状态

❌ 错误 3:状态中写阻塞代码

c 复制代码
// 错误示例
case STATE_RUN:
    HAL_Delay(1000);  // ❌ 阻塞延时
    ProcessData();
    break;

// 正确示例
case STATE_RUN:
    if (currentTime - lastTime > 1000) {  // ✅ 非阻塞
        ProcessData();
        lastTime = currentTime;
    }
    break;

原则

  • 状态机应该快速执行
  • 使用定时器而不是延时
  • 异步处理长时间操作

❌ 错误 4:事件不清晰

c 复制代码
// 错误示例:用标志位判断
if (flag1 && flag2 && !flag3) {  // ❌ 逻辑混乱
    state = STATE_RUN;
}

// 正确示例:明确的事件
if (event == EVENT_START && !errorFlag) {  // ✅ 清晰
    state = STATE_RUN;
}

原则

  • 定义明确的事件类型
  • 事件名称具有描述性
  • 避免复杂的条件判断

❌ 错误 5:没有 ERROR 状态

c 复制代码
// 错误示例:没有错误处理
switch (state) {
    case STATE_IDLE:
    case STATE_RUN:
}
// ❌ 出错了怎么办?

// 正确示例:有错误状态
switch (state) {
    case STATE_IDLE:
    case STATE_RUN:
    case STATE_ERROR:  // ✅ 错误处理
        if (resetCmd) {
            state = STATE_IDLE;
        }
        break;
}

原则

  • 总是有错误/异常状态
  • 错误状态有恢复机制
  • 记录错误日志

❌ 错误 6:状态图和代码不一致

c 复制代码
// 设计阶段画了状态图
// 开发阶段随意修改代码
// 两者完全不一致
// ❌ 文档失去意义

// 正确做法
// 1. 修改代码时同步更新状态图
// 2. 代码注释中引用状态图
// 3. 代码审查时检查一致性

原则

  • 状态图是活文档
  • 代码变动时更新图
  • 定期检查一致性

九、调试与优化技巧

1. 状态日志

c 复制代码
void StateMachine_SetState(State_t newState)
{
    State_t oldState = currentState;
    currentState = newState;
    
    // 状态变化日志
    if (oldState != newState) {
        printf("[%lu] State: %s -> %s\n",
               HAL_GetTick(),
               GetStateName(oldState),
               GetStateName(newState));
    }
}

const char* GetStateName(State_t state)
{
    switch (state) {
        case STATE_IDLE:  return "IDLE";
        case STATE_RUN:   return "RUN";
        case STATE_ERROR: return "ERROR";
        default:          return "UNKNOWN";
    }
}

2. 状态可视化(LED 指示)

c 复制代码
void UpdateStatusLED(void)
{
    switch (currentState)
    {
        case STATE_IDLE:
            LED_Green();
            break;
        case STATE_RUN:
            LED_Blue_Blink();
            break;
        case STATE_ERROR:
            LED_Red();
            break;
    }
}

3. 状态持续时间监测

c 复制代码
typedef struct {
    State_t state;
    uint32_t enterTime;
    uint32_t duration;
} StateInfo_t;

StateInfo_t stateInfo;

void OnStateEnter(State_t state)
{
    stateInfo.state = state;
    stateInfo.enterTime = HAL_GetTick();
}

void UpdateStateDuration(void)
{
    stateInfo.duration = HAL_GetTick() - stateInfo.enterTime;
    
    // 检测异常长时间停留
    if (stateInfo.duration > 10000) {
        printf("Warning: State %s timeout\n", GetStateName(stateInfo.state));
    }
}

4. 状态转换计数

c 复制代码
uint32_t transitionCount[STATE_MAX][STATE_MAX];

void RecordTransition(State_t from, State_t to)
{
    transitionCount[from][to]++;
}

void PrintTransitionStatistics(void)
{
    printf("State Transition Statistics:\n");
    for (int i = 0; i < STATE_MAX; i++) {
        for (int j = 0; j < STATE_MAX; j++) {
            if (transitionCount[i][j] > 0) {
                printf("%s -> %s: %lu\n",
                       GetStateName(i),
                       GetStateName(j),
                       transitionCount[i][j]);
            }
        }
    }
}

十、PlantUML 绘制指南

基本语法

plantuml 复制代码
@startuml

[*] --> State1

state State1 {
  State1 : entry: Action1()
  State1 : do: Activity()
  State1 : exit: Action2()
}

State1 --> State2 : event[condition] / action
State2 --> [*]

@enduml

常用元素

元素 语法 说明
初始状态 [*] 黑色实心圆
终止状态 [*] 圆圈内有实心圆
状态 state Name 圆角矩形
转换 S1 --> S2 : event 箭头
守卫条件 event[guard] 方括号
动作 event / action 斜杠
Entry entry: Action() 冒号
Exit exit: Action() 冒号
Do do: Activity() 冒号

完整示例

plantuml 复制代码
@startuml DeviceStateMachine

title 设备控制状态机

[*] --> INIT

state INIT {
  INIT : entry: HW_Init()
}

state IDLE {
  IDLE : entry: LED_Off()
}

state RUN {
  RUN : entry: Motor_Start()
  RUN : do: ReadSensors()
  RUN : exit: Motor_Stop()
}

state ERROR {
  ERROR : entry: LED_Red()
  ERROR : do: LED_Blink()
}

INIT --> IDLE : init_done
IDLE --> RUN : start_cmd
RUN --> IDLE : stop_cmd
RUN --> ERROR : error[temp > 80] / Alarm()
ERROR --> IDLE : reset_cmd

note right of RUN
  运行状态下持续监测温度
  超过80度自动进入错误状态
end note

@enduml

十一、总结与最佳实践

状态图的核心价值

复制代码
1. 设计工具:先画图再写代码
2. 沟通工具:统一团队理解
3. 调试工具:对照检查逻辑
4. 文档工具:维护和交接

使用建议

复制代码
✅ 写代码前先画状态图
✅ 调试时对照状态图
✅ 代码变动时更新状态图
✅ 状态数量控制在 3-7 个
✅ 总是有错误处理状态
✅ 使用非阻塞代码
✅ 明确的事件定义

附录:参考资源

  • UML 2.5 State Machine Diagram Specification
  • "Practical UML Statecharts in C/C++" - Miro Samek
  • PlantUML 官网:https://plantuml.com
  • 状态机设计模式
相关推荐
就不掉头发2 小时前
HTTP基本知识
网络·网络协议·http
小林有点嵌2 小时前
UML之类图学习
学习·uml
小林有点嵌2 小时前
UML之用例图学习
学习·microsoft·uml
Blurpath2 小时前
什么是 ISP 代理?双 ISP 代理又是什么?一文讲清原理与应用场景
服务器·网络·ip代理·静态代理·住宅代理
_F_y2 小时前
网络基础概念
网络
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [fs][fs_parser]
linux·笔记·学习
专业机床数据采集3 小时前
西门子数控数采集变量与说明对照表
大数据·网络·cnc数据采集
白帽子凯哥哥3 小时前
在学习SQL注入或XSS这类具体漏洞时,如何设计一个高效的“理论+实践”学习循环?
sql·学习·漏洞·xss
ACP广源盛139246256733 小时前
GSV6701A@ACP#6701A产品规格详解及产品应用分享
网络·嵌入式硬件·音视频