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 即可,本最小实现未包含该扩展。