1. 电梯控制系统状态机
任务目标
设计并实现一个电梯控制系统的有限状态机(FSM),包含空闲(Idle)、运行(Moving)、开门(DoorOpen)、关门(DoorClosed)四个核心状态,处理楼层请求与紧急停止事件。系统需响应外部按钮请求,在状态间正确迁移,并保证紧急停止时优先进入安全状态。
状态定义与迁移逻辑
- Idle(空闲):电梯静止在某楼层,无请求。收到楼层请求 → Moving;收到紧急停止 → 保持Idle(无动作)。
- Moving(运行):电梯向目标楼层移动。到达目标楼层 → DoorOpen;收到紧急停止 → 紧急状态(Emergency)。
- DoorOpen(开门):电梯门开启,等待乘客。关门超时或收到关门指令 → DoorClosed;收到紧急停止 → Emergency。
- DoorClosed(关门):门已关闭,准备响应新请求。若有新楼层请求 → Moving;无请求 → Idle;收到紧急停止 → Emergency。
- Emergency(紧急):紧急停止状态,电梯停止一切运动并保持门关闭。收到复位信号 → Idle。
完整实现代码
#include <stdio.h>
#include <stdlib.h>
typedef enum {
IDLE,
MOVING,
DOOR_OPEN,
DOOR_CLOSED,
EMERGENCY
} State;
typedef enum {
EV_FLOOR_REQUEST, // 楼层请求
EV_ARRIVED, // 到达目标楼层
EV_DOOR_TIMEOUT, // 开门超时
EV_CLOSE_DOOR, // 手动关门
EV_EMERGENCY_STOP, // 紧急停止
EV_RESET // 复位
} Event;
typedef struct {
State current_state;
int current_floor;
int target_floor;
} Elevator;
void init_elevator(Elevator *e) {
e->current_state = IDLE;
e->current_floor = 1;
e->target_floor = 1;
}
const char* state_name(State s) {
switch (s) {
case IDLE: return "IDLE";
case MOVING: return "MOVING";
case DOOR_OPEN: return "DOOR_OPEN";
case DOOR_CLOSED: return "DOOR_CLOSED";
case EMERGENCY: return "EMERGENCY";
default: return "UNKNOWN";
}
}
void handle_event(Elevator *e, Event ev) {
State s = e->current_state;
printf("[%s] + ", state_name(s));
switch (s) {
case IDLE:
if (ev == EV_FLOOR_REQUEST) {
e->current_state = MOVING;
printf("楼层请求 → MOVING\n");
} else {
printf("忽略事件\n");
}
break;
case MOVING:
if (ev == EV_ARRIVED) {
e->current_state = DOOR_OPEN;
printf("到达目标楼层 → DOOR_OPEN\n");
} else if (ev == EV_EMERGENCY_STOP) {
e->current_state = EMERGENCY;
printf("紧急停止 → EMERGENCY\n");
} else {
printf("忽略事件\n");
}
break;
case DOOR_OPEN:
if (ev == EV_DOOR_TIMEOUT || ev == EV_CLOSE_DOOR) {
e->current_state = DOOR_CLOSED;
printf("关门 → DOOR_CLOSED\n");
} else if (ev == EV_EMERGENCY_STOP) {
e->current_state = EMERGENCY;
printf("紧急停止 → EMERGENCY\n");
} else {
printf("忽略事件\n");
}
break;
case DOOR_CLOSED:
if (ev == EV_FLOOR_REQUEST) {
e->current_state = MOVING;
printf("新请求 → MOVING\n");
} else if (ev == EV_EMERGENCY_STOP) {
e->current_state = EMERGENCY;
printf("紧急停止 → EMERGENCY\n");
} else {
e->current_state = IDLE;
printf("无请求 → IDLE\n");
}
break;
case EMERGENCY:
if (ev == EV_RESET) {
e->current_state = IDLE;
printf("复位 → IDLE\n");
} else {
printf("紧急状态,仅接受复位\n");
}
break;
default:
break;
}
}
int main() {
Elevator elev;
init_elevator(&elev);
printf("初始状态: %s (楼层 %d)\n\n", state_name(elev.current_state), elev.current_floor);
// 测试场景1:空闲 → 运行 → 开门 → 关门 → 空闲
handle_event(&elev, EV_FLOOR_REQUEST); // IDLE → MOVING
handle_event(&elev, EV_ARRIVED); // MOVING → DOOR_OPEN
handle_event(&elev, EV_DOOR_TIMEOUT); // DOOR_OPEN → DOOR_CLOSED
handle_event(&elev, EV_CLOSE_DOOR); // DOOR_CLOSED 无请求 → IDLE
printf("\n--- 紧急停止测试 ---\n");
handle_event(&elev, EV_FLOOR_REQUEST); // IDLE → MOVING
handle_event(&elev, EV_EMERGENCY_STOP); // MOVING → EMERGENCY
handle_event(&elev, EV_FLOOR_REQUEST); // EMERGENCY 忽略
handle_event(&elev, EV_RESET); // EMERGENCY → IDLE
printf("\n最终状态: %s\n", state_name(elev.current_state));
return 0;
}
编译与运行
gcc -o elevator_fsm elevator_fsm.c
./elevator_fsm
验证方法与通过条件
程序输出应展示以下状态迁移序列,满足即判定通过:
初始状态: IDLE (楼层 1)
[IDLE] + 楼层请求 → MOVING
[MOVING] + 到达目标楼层 → DOOR_OPEN
[DOOR_OPEN] + 开门超时 → DOOR_CLOSED
[DOOR_CLOSED] + 手动关门 → IDLE
--- 紧急停止测试 ---
[IDLE] + 楼层请求 → MOVING
[MOVING] + 紧急停止 → EMERGENCY
[EMERGENCY] + 楼层请求 → 紧急状态,仅接受复位
[EMERGENCY] + 复位 → IDLE
最终状态: IDLE
通过条件:所有状态迁移与上述预期输出完全一致;紧急状态下非复位事件被正确忽略;最终状态回到IDLE。
状态机迁移图
关键说明
- 本实现使用事件驱动方式处理状态迁移,
handle_event函数为核心逻辑,通过 switch-case 结构清晰表达每个状态对事件的处理。 - 紧急停止(EMERGENCY)状态优先级最高,一旦进入,除复位外所有事件均被忽略,符合电梯安全规范。
- 实际工程中,楼层请求需携带目标楼层参数,本案例为聚焦FSM核心逻辑,将请求简化为无参事件;若需扩展,可在
Event中增加参数或使用独立请求队列。