3. 电梯控制系统状态机
任务目标
实现一个电梯控制系统状态机,管理静止、上升、下降、开门、关门五种状态,处理内部楼层请求与开关门超时事件。系统需根据当前状态和输入事件正确迁移状态,并输出电机与门控动作。
状态与事件定义
| 状态 | 含义 | 进入时动作 |
|---|---|---|
| IDLE | 静止待命 | 停止电机 |
| UP | 上升中 | 电机上行 |
| DOWN | 下降中 | 电机下行 |
| DOOR_OPEN | 开门状态 | 开门,启动超时定时器 |
| DOOR_CLOSE | 关门状态 | 关门,启动超时定时器 |
输入事件:FLOOR_REQ(n)(请求前往n层)、DOOR_TIMEOUT(开门/关门超时)、ARRIVED(到达目标楼层)。
核心实现
// elevator_fsm.c
#include <stdio.h>
#include <stdlib.h>
typedef enum { IDLE, UP, DOWN, DOOR_OPEN, DOOR_CLOSE } State;
typedef enum { EV_FLOOR_REQ, EV_ARRIVED, EV_DOOR_TIMEOUT } Event;
typedef struct {
State state;
int current_floor;
int target_floor;
int has_request;
} Elevator;
void motor_up(void) { printf("[电机] 上行\n"); }
void motor_down(void) { printf("[电机] 下行\n"); }
void motor_stop(void) { printf("[电机] 停止\n"); }
void open_door(void) { printf("[门] 打开\n"); }
void close_door(void) { printf("[门] 关闭\n"); }
void enter_state(Elevator *e, State s) {
e->state = s;
switch (s) {
case IDLE: motor_stop(); break;
case UP: motor_up(); break;
case DOWN: motor_down(); break;
case DOOR_OPEN: open_door(); break;
case DOOR_CLOSE: close_door(); break;
}
}
void handle_event(Elevator *e, Event ev, int floor) {
switch (e->state) {
case IDLE:
if (ev == EV_FLOOR_REQ) {
e->target_floor = floor;
e->has_request = 1;
if (floor > e->current_floor) enter_state(e, UP);
else if (floor < e->current_floor) enter_state(e, DOWN);
else { enter_state(e, DOOR_OPEN); e->has_request = 0; }
}
break;
case UP:
if (ev == EV_ARRIVED && floor == e->target_floor) {
e->current_floor = floor;
e->has_request = 0;
enter_state(e, DOOR_OPEN);
}
break;
case DOWN:
if (ev == EV_ARRIVED && floor == e->target_floor) {
e->current_floor = floor;
e->has_request = 0;
enter_state(e, DOOR_OPEN);
}
break;
case DOOR_OPEN:
if (ev == EV_DOOR_TIMEOUT) enter_state(e, DOOR_CLOSE);
break;
case DOOR_CLOSE:
if (ev == EV_DOOR_TIMEOUT) {
if (e->has_request) {
if (e->target_floor > e->current_floor) enter_state(e, UP);
else if (e->target_floor < e->current_floor) enter_state(e, DOWN);
else { e->has_request = 0; enter_state(e, DOOR_OPEN); }
} else {
enter_state(e, IDLE);
}
}
break;
}
}
// 测试入口
int main(void) {
Elevator e = { IDLE, 1, 0, 0 };
printf("初始:1楼静止\n");
handle_event(&e, EV_FLOOR_REQ, 5); // 1楼→5楼
handle_event(&e, EV_ARRIVED, 5); // 到达5楼
handle_event(&e, EV_DOOR_TIMEOUT); // 开门超时
handle_event(&e, EV_DOOR_TIMEOUT); // 关门超时
handle_event(&e, EV_FLOOR_REQ, 2); // 5楼→2楼
handle_event(&e, EV_ARRIVED, 2);
handle_event(&e, EV_DOOR_TIMEOUT);
handle_event(&e, EV_DOOR_TIMEOUT);
return 0;
}
编译与运行
gcc -o elevator_fsm elevator_fsm.c
./elevator_fsm
验证方法
运行程序后,观察输出序列是否满足以下判定条件:
- 从1楼请求去5楼,先输出上行,到达后输出开门;
- 开门超时后输出关门,关门超时后无新请求则输出停止;
- 从5楼请求去2楼,先输出下行,到达后再次执行开门→关门→停止流程。
若输出顺序与上述一致,且状态迁移符合“静止→上升→开门→关门→静止”的闭环,则判定通过。
状态迁移图
关键说明
- 本实现采用事件驱动方式,
handle_event为唯一状态迁移入口,所有动作在状态进入时执行。 - 实际工程中,
ARRIVED事件由楼层传感器触发,DOOR_TIMEOUT由定时器中断产生,此处以测试序列模拟。 - 若需处理运行中新的楼层请求(如上升途中有人按了更高层),可在 UP/DOWN 状态增加对
EV_FLOOR_REQ的处理,更新target_floor即可,本最小实现未包含该扩展。