从洗衣机到单片机:用生活例子秒懂状态机,在STC89C52上做个自动售货机模型

张开发
2026/4/9 12:30:39 15 分钟阅读

分享文章

从洗衣机到单片机:用生活例子秒懂状态机,在STC89C52上做个自动售货机模型
从洗衣机到单片机用生活例子秒懂状态机在STC89C52上做个自动售货机模型每次按下洗衣机的启动按钮它都会按照浸泡→洗涤→漂洗→脱水的固定流程运转——这种看似简单的机械行为背后隐藏着状态机的精妙设计。状态机就像一位经验丰富的管家它清楚地知道在什么情况下该做什么事并且严格按照预设的规则行动。今天我们就从这些生活场景出发用STC89C52单片机搭建一个趣味十足的自动售货机模型让抽象的状态机概念变得触手可及。1. 生活中的状态机课堂1.1 洗衣机的状态舞蹈观察一台全自动洗衣机的工作流程我们会发现它总是在几个固定状态间切换待机状态显示屏亮着等待用户操作注水状态进水阀打开水位传感器监测水量洗涤状态电机正反转交替运行排水状态水泵启动水位下降脱水状态高速旋转甩干衣物这些状态之间的转换并非随意发生。例如只有当水位达到设定值这个条件满足时才会从注水状态切换到洗涤状态。这种状态-条件-动作的对应关系正是状态机的核心特征。1.2 交通信号灯的节奏大师路口的红绿灯是另一个经典案例。一个标准的双向交通灯包含以下状态组合状态编号主路信号支路信号持续时间S0绿灯红灯30秒S1黄灯红灯5秒S2红灯绿灯20秒S3红灯黄灯5秒这个系统会按照S0→S1→S2→S3的顺序循环切换每个状态的持续时间由定时器控制。如果我们在深夜为它增加一个黄灯闪烁的特殊状态就扩展出了一个更智能的状态机。2. 状态机的三大核心要素2.1 状态定义的艺术在设计状态机时首先要明确系统的所有可能状态。以我们即将制作的自动售货机为例可以考虑以下状态typedef enum { IDLE, // 待机状态 COIN_INSERTED, // 投币状态 ITEM_SELECTED, // 选择商品 DISPENSING, // 出货中 CHANGE_GIVING // 找零中 } VendingState;关键技巧状态划分要遵循互斥且完备原则即任何时候系统只处于一个明确状态且所有可能情况都被覆盖。2.2 触发事件的识别事件是状态转换的催化剂。在售货机系统中典型事件包括硬币投入COIN_IN事件商品按钮按下SELECT事件出货完成DISPENSE_DONE事件找零完成CHANGE_DONE事件2.3 状态转移图的绘制用图形化方式表示状态转换逻辑会更加直观[IDLE] --COIN_IN-- [COIN_INSERTED] [COIN_INSERTED] --SELECT-- [ITEM_SELECTED] [ITEM_SELECTED] --DISPENSE-- [DISPENSING] [DISPENSING] --DISPENSE_DONE-- [CHANGE_GIVING] [CHANGE_GIVING] --CHANGE_DONE-- [IDLE]这个简单的有向图清晰地展示了状态之间的转换路径和触发条件。3. STC89C52硬件准备3.1 所需材料清单制作售货机模型需要以下组件STC89C52RC单片机最小系统板5个LED灯分别表示电源、投币、选择、出货、找零2个轻触按键模拟投币和选择1位数码管显示金额面包板和杜邦线若干3.2 硬件连接示意图关键引脚连接配置单片机引脚连接器件功能说明P1.0LED1电源指示灯P1.1LED2投币状态指示P1.2LED3选择状态指示P1.3LED4出货状态指示P1.4LED5找零状态指示P3.2KEY1投币按键P3.3KEY2选择按键P2.0-P2.7数码管段选金额显示4. 售货机状态机实现详解4.1 状态枚举与变量定义首先在代码中定义状态机和相关变量#include reg52.h // 状态定义 typedef enum { IDLE, COIN_INSERTED, ITEM_SELECTED, DISPENSING, CHANGE_GIVING } VendingState; // 事件定义 typedef enum { NO_EVENT, COIN_IN, SELECT, DISPENSE_DONE, CHANGE_DONE } VendingEvent; VendingState currentState IDLE; unsigned char balance 0; // 当前余额4.2 状态转移函数实现核心状态处理逻辑如下void handleVendingState(VendingEvent event) { switch(currentState) { case IDLE: if(event COIN_IN) { balance 1; // 每次投币增加1元 P1 0x02; // 点亮投币LED currentState COIN_INSERTED; } break; case COIN_INSERTED: if(event COIN_IN) { balance 1; } else if(event SELECT balance 3) { P1 0x04; // 点亮选择LED currentState ITEM_SELECTED; } break; case ITEM_SELECTED: if(event DISPENSE_DONE) { P1 0x08; // 点亮出货LED balance - 3; // 商品价格3元 currentState DISPENSING; } break; case DISPENSING: if(event CHANGE_DONE) { P1 0x10; // 点亮找零LED currentState CHANGE_GIVING; } break; case CHANGE_GIVING: if(balance 0) { P1 0x01; // 返回待机状态 currentState IDLE; } else { balance--; // 逐个退币 } break; } // 更新数码管显示 P2 balance; }4.3 主循环与事件检测在主程序中不断检测按键事件void main() { P1 0x01; // 初始化电源LED亮 while(1) { if(P3_2 0) { // 投币按键按下 delayMs(20); // 消抖处理 if(P3_2 0) { handleVendingState(COIN_IN); while(!P3_2); // 等待按键释放 } } if(P3_3 0 currentState COIN_INSERTED) { // 选择按键 delayMs(20); if(P3_3 0 balance 3) { handleVendingState(SELECT); // 模拟出货过程 delayMs(1000); handleVendingState(DISPENSE_DONE); // 模拟找零过程 delayMs(500); handleVendingState(CHANGE_DONE); while(!P3_3); } } } }5. 状态机优化技巧5.1 使用状态表简化逻辑对于复杂状态机可以用查表法替代switch-casetypedef struct { VendingState current; VendingEvent event; void (*action)(void); VendingState next; } StateTransition; const StateTransition stateTable[] { {IDLE, COIN_IN, addCoin, COIN_INSERTED}, {COIN_INSERTED, COIN_IN, addCoin, COIN_INSERTED}, {COIN_INSERTED, SELECT, selectItem, ITEM_SELECTED}, // 其他状态转换规则... }; void processEvent(VendingEvent event) { for(int i0; isizeof(stateTable)/sizeof(stateTable[0]); i) { if(stateTable[i].current currentState stateTable[i].event event) { stateTable[i].action(); currentState stateTable[i].next; break; } } }5.2 添加超时保护机制为防止系统卡死在某个状态需要添加超时检测unsigned int timeoutCounter 0; void checkTimeout() { timeoutCounter; if(timeoutCounter MAX_TIMEOUT) { // 复位到安全状态 currentState IDLE; timeoutCounter 0; P1 0x01; // 仅电源LED亮 } }在状态处理函数中每次状态转换时重置超时计数器。5.3 引入层次化状态机当系统复杂度增加时可以采用层次化状态机设计// 顶层状态 typedef enum { OPERATIONAL, MAINTENANCE, ERROR } TopLevelState; // 运行子状态 typedef enum { NORMAL, PROMOTION, TEST } OperationalState; TopLevelState topState; OperationalState opState;这种设计允许在不同层次处理不同粒度的状态逻辑大大提升复杂系统的可管理性。

更多文章