1. 项目概述
作为一名嵌入式系统开发者,我最近完成了一个基于STM32的自动售货机控制系统项目。这个系统从硬件选型到软件设计都经过精心考量,特别适合想要学习嵌入式系统开发或对自动售货机原理感兴趣的同行参考。
这个系统最核心的特点是采用了模块化设计思路,将复杂的售货机功能分解为多个相对独立的子系统,包括主控模块、投币识别模块、商品出货模块、人机交互模块等。每个模块都可以单独开发和测试,最后再整合成一个完整的系统。这种设计方式不仅降低了开发难度,也便于后期的维护和功能扩展。
2. 硬件系统设计与选型
2.1 主控芯片选型
在项目初期,我面临的首要问题就是选择合适的主控芯片。经过详细比较,最终在80C51和STM32之间选择了后者,主要基于以下几个关键考量:
-
处理能力:STM32F103C8T6采用Cortex-M3内核,主频可达72MHz,远高于80C51的12MHz(典型值)。这对于需要实时处理投币信号、控制多个电机并同时更新显示的售货机系统来说至关重要。
-
存储资源:STM32内置64KB Flash和20KB SRAM,而80C51仅有4KB ROM和128B RAM。更大的存储空间意味着我们可以实现更复杂的业务逻辑,存储更多商品信息,甚至未来可以加入销售统计功能。
-
外设丰富度:STM32自带多个USART、SPI、I2C接口,还有ADC和定时器等,这些资源让我们可以轻松连接各种外设,而不需要额外扩展芯片。
-
开发便利性:基于ARM架构的STM32有更完善的开发工具链和更活跃的社区支持,遇到问题时更容易找到解决方案。
提示:对于预算有限的教学项目,80C51仍然是不错的选择,但商业产品建议优先考虑STM32等32位MCU。
2.2 投币器选型与接口设计
投币器是自动售货机的"收银员",其可靠性直接影响用户体验。我们对比了两种主流投币器:
TW-2020型硬币器特点:
- 支持退币功能,符合现代售货机操作习惯
- 记忆功能稳定,断电后设置不会丢失
- 采用标准4针防反插接口,安装方便
- 工作电压5-12V,与系统电源兼容
硬件连接方面,投币器主要通过以下信号与主控通信:
- 脉冲信号输出:每识别到一个有效硬币就输出一个脉冲
- 币种识别信号:高/低电平表示不同面额
- 退币控制信号:MCU通过此信号触发退币电机
实际接线时需要注意:
- 信号线建议使用屏蔽线,防止干扰
- 接地点要统一,避免地环路引入噪声
- 在I/O口加上适当的滤波电容
2.3 出货电机选型与驱动
出货机构是自动售货机最容易出故障的部分之一。经过反复测试,我们最终选择了CY-VGMS-277弹簧电机,主要因为:
-
稳定性:弹簧式出货方式对瓶装饮料特别友好,避免了传统推杆可能造成的摇晃和碰撞。
-
安装便利:模块化设计,通过卡扣固定,维护时可以直接整体更换。
-
三重检测:
- 机械出货检测
- 红外缺货检测
- 出货完成检测
电机驱动电路设计要点:
- 采用光耦隔离MCU和电机电源
- 使用MOSFET作为功率开关元件
- 添加续流二极管保护电路
- 工作电流建议留有30%余量
2.4 电源系统设计
自动售货机的电源系统需要为不同模块提供多种电压:
-
主电源架构:
- AC220V输入
- 通过S-50-24开关电源转换为DC24V(供电机使用)
- DC24V再降压为DC12V(供投币器使用)
- 最后通过AMS1117系列LDO得到DC5V和DC3.3V
-
关键设计考虑:
- 电机启动时的电流冲击问题
- 各电压轨的隔离和滤波
- 备用电池的考虑(可选)
-
实际布线技巧:
- 大电流线路(如电机供电)要使用足够粗的线径
- 数字和模拟部分电源要分开走线
- 合理布置去耦电容(每芯片至少0.1μF)
3. 软件系统设计
3.1 开发环境搭建
我们选择Keil μVision5作为主要开发环境,配合ST-Link调试器。环境配置步骤如下:
- 安装Keil MDK基础包
- 通过Pack Installer添加STM32F1系列支持
- 配置项目选项:
- 选择正确的芯片型号(STM32F103C8T6)
- 设置调试工具为ST-Link
- 优化级别选择-O2平衡优化
- 添加必要的库文件:
- CMSIS核心库
- STM32标准外设库
- OLED驱动等第三方库
注意:确保在Options for Target -> Target选项卡中正确设置晶振频率(根据实际硬件,通常8MHz)
3.2 系统主程序设计
主程序采用经典的前后台架构,下面是简化后的伪代码:
c复制int main(void) {
// 硬件初始化
SystemInit();
GPIO_Init();
USART_Init();
TIM_Init();
OLED_Init();
// 外设初始化
CoinAcceptor_Init();
Motor_Init();
Key_Init();
// 主循环
while(1) {
Key_Process(); // 按键扫描
Coin_Process(); // 投币处理
Display_Update(); // 显示更新
if(SystemState == STATE_DELIVER) {
Motor_Control(); // 出货控制
}
// 低功耗处理
__WFI();
}
}
3.3 关键功能模块实现
3.3.1 投币处理流程
投币处理是售货机的核心功能之一,其状态机设计如下:
- 空闲状态:等待投币信号
- 投币检测:通过外部中断捕获投币脉冲
- 金额累计:根据币种信号累计金额
- 显示更新:实时显示已投金额
- 超时处理:30秒无操作自动退币
对应的代码实现要点:
c复制void EXTI0_IRQHandler(void) {
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
// 确认是有效投币信号
if(CheckCoinValid()) {
TotalMoney += GetCoinValue();
UpdateDisplay();
ResetTimeoutCounter();
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
3.3.2 出货控制逻辑
出货控制需要考虑以下几个关键点:
-
电机驱动时序:
- 启动信号至少维持500ms
- 两次出货间隔不小于1秒
- 出货完成后检测确认信号
-
异常处理:
- 出货超时(3秒未完成)
- 卡货检测(通过红外传感器)
- 连续故障处理(最多重试2次)
-
对应代码片段:
c复制void DeliverGoods(uint8_t channel) {
uint8_t retry = 0;
while(retry < MAX_RETRY) {
Motor_On(channel);
Delay_ms(500);
Motor_Off(channel);
if(CheckDeliveryOK(channel)) {
break; // 出货成功
}
retry++;
if(retry == MAX_RETRY) {
SetErrorState(ERR_DELIVERY_FAILED);
}
}
}
3.4 人机交互设计
3.4.1 OLED显示界面
我们使用1.3寸OLED显示以下信息:
- 商品列表及价格
- 已选商品及数量
- 投入金额
- 还需投入金额
- 系统状态提示
显示刷新采用部分刷新策略,只有内容变化时才更新对应区域,以降低功耗。
3.4.2 按键输入处理
5个按键的功能分配:
- SW0:商品选择(循环切换)
- SW1:数量增加
- SW2:数量减少
- SW3:确认/出货
- SW4:取消/退币
按键消抖采用硬件(RC滤波)+软件(20ms延时确认)双重措施。
4. 系统调试与优化
4.1 Proteus仿真验证
在硬件制作前,我们先在Proteus中搭建了完整的仿真模型:
-
主要仿真内容:
- 电源系统工作状态
- 主控与外设的通信
- 投币信号处理流程
- 出货电机控制时序
-
仿真发现的问题:
- 投币器信号抖动导致误计数
- 电机启动时电源电压跌落
- 按键扫描占用过多CPU时间
-
解决方案:
- 在投币信号输入增加施密特触发器
- 优化电源滤波电路设计
- 将按键扫描改为中断方式
4.2 实际硬件调试
硬件调试阶段遇到的主要问题及解决方法:
-
问题一:出货不稳定
- 现象:偶尔会出现多出货或少出货
- 原因:电机驱动信号受到干扰
- 解决:增加光耦隔离,缩短信号线长度
-
问题二:投币识别率低
- 现象:某些硬币识别率只有80%左右
- 原因:电源纹波过大影响投币器工作
- 解决:在投币器电源端增加LC滤波
-
问题三:显示闪烁
- 现象:出货时OLED会出现短暂闪烁
- 原因:电机工作时引起电源波动
- 解决:为显示模块单独供电
4.3 性能优化措施
经过测试后实施的优化:
-
电源系统优化:
- 增加大容量储能电容(电机电源端)
- 采用分离式走线(数字/模拟/功率)
-
软件优化:
- 将主循环周期从10ms调整为20ms
- 采用事件驱动代替轮询
- 启用STM32的硬件CRC校验
-
可靠性提升:
- 增加看门狗定时器
- 关键数据写入Flash备份
- 异常状态自动恢复机制
5. 项目总结与扩展建议
5.1 实际应用效果
经过完整测试周期,系统主要指标如下:
- 投币识别准确率:≥99.5%
- 出货成功率:100%(标准测试条件下)
- 待机功耗:<3W
- 响应时间:<200ms(按键到动作)
5.2 可扩展功能
基于现有系统,可以进一步扩展:
- 非现金支付模块(扫码支付)
- 远程监控和管理功能
- 销售数据统计和分析
- 温度控制(适用于饮料冷藏)
5.3 经验分享
在项目开发过程中,有几个特别值得注意的经验:
-
模块化测试:每个功能模块都应该先单独测试,再集成到系统中。这样可以快速定位问题。
-
电源设计余量:电机的启动电流往往是额定电流的3-5倍,电源设计必须考虑这一点。
-
防反接保护:所有外部接口都应该考虑防反接设计,特别是投币器和出货电机这类经常需要维护的部件。
-
EMC设计:售货机通常安装在公共场所,良好的电磁兼容设计可以避免很多奇怪的问题。
这个项目从构思到完成大约用了3个月时间,期间遇到了不少挑战,但最终实现的系统稳定可靠。对于想要学习嵌入式系统开发的朋友来说,自动售货机是一个很好的练手项目,它涵盖了硬件设计、外设驱动、状态机编程等多个重要知识点。