第一章:课程导论与硬件基础

各位同学好,我是你们这门课的老张。做嵌入式开发十几年了,从最早的8位单片机一路做到现在的双核处理器。今天咱们聊的这门课,说白了就是教你怎么让点钞机变得更聪明——能远程升级、能自我诊断、出了问题还能远程修复。

点钞机这东西,看着不起眼,其实是个典型的嵌入式系统。我当年刚入行时,总觉得点钞机就是个电机加几个传感器,后来吃过亏才明白,这里面的门道深着呢。

1.1 点钞机嵌入式系统架构

先说说点钞机的整体架构。你拆开一台现代点钞机,会发现它其实是个三层结构:

  • 感知层:各种传感器,比如红外对管、磁头、厚度传感器、图像传感器。这些家伙负责“看”和“摸”钞票。
  • 控制层:主控芯片加上电机驱动、电磁铁驱动。负责“动手”——搓钞、分钞、整理。
  • 处理层:主控芯片的核心算法,负责“动脑”——识别面额、鉴伪、计数。

我个人习惯把这三层比作人的五官、手脚和大脑。缺了哪个都不行。

这里有个关键点:点钞机的实时性要求很高。钞票以每秒15张的速度飞过传感器,你必须在几毫秒内完成采集、处理、判断、响应。我在项目中遇到过,某次因为中断响应慢了2毫秒,结果钞票识别率直接掉了5个百分点。

核心要点:点钞机的嵌入式系统,本质上是一个强实时、多任务、高可靠的嵌入式系统。它的固件不仅要跑得快,还要跑得稳。

1.2 主控芯片选型:STM32 vs ESP32

选主控芯片,是每个点钞机项目的第一步。市面上主流的选择就两个:STM32和ESP32。我两个都用过,说说我的感受。

对比项 STM32 ESP32
内核 Cortex-M系列(M3/M4/M7) Xtensa LX6双核
主频 72MHz ~ 480MHz 160MHz ~ 240MHz
无线能力 无(需外挂WiFi/BT模块) 内置WiFi+蓝牙
实时性 优秀(硬件定时器、中断响应快) 良好(但FreeRTOS调度有抖动)
生态 成熟,文档丰富,库函数稳定 活跃,但部分库不够稳定
成本 中等(STM32F4约15-25元) 较低(ESP32约10-15元)

你可能会问:那到底选哪个?我的建议是:

  • 如果点钞机需要联网(比如远程维护、固件升级),选ESP32。它自带WiFi,省一个模块的钱和空间。
  • 如果对实时性要求极高(比如高速点钞、多传感器同步),选STM32。它的硬件定时器和DMA通道更可靠。
  • 如果项目周期紧,选STM32。它的HAL库和CubeMX工具能帮你快速上手。

我的经验:我做过一个项目,客户要求点钞机支持OTA升级,但主控选了STM32F4。结果我们不得不外挂一个ESP8266模块做WiFi,不仅增加了成本,还多了个通信故障点。后来我学乖了——如果明确需要无线功能,直接上ESP32

1.3 固件存储与启动流程

固件存在哪?怎么启动?这是每个嵌入式工程师必须搞明白的事。点钞机的固件存储,通常分三块:

  • Bootloader:引导程序,负责检查固件、决定启动哪个版本。
  • 主固件区:存放正常运行的程序。
  • 备份固件区:存放上一个稳定版本,用于回滚。

启动流程大概是这样的:

  1. 上电后,芯片从0x08000000地址开始执行(这是STM32的Flash起始地址)。
  2. Bootloader先检查主固件区的CRC校验。如果校验通过,跳转到主固件。
  3. 如果校验失败(比如升级过程中断电了),Bootloader自动从备份区加载固件。
  4. 如果两个区都坏了...嗯,那就只能进厂返修了。

这里有个细节:中断向量表的重映射。Bootloader和主固件都有自己的中断向量表。Bootloader启动后,必须把中断向量表地址改成主固件的地址,否则中断来了会跑错地方。

避坑指南:我曾经在项目里犯过这个错——Bootloader跳转到主固件后,忘了重新设置中断向量表偏移。结果点钞机一启动就死机,查了两天才找到原因。后来我养成了习惯:每次跳转前,都检查一下SCB->VTOR寄存器

代码示例(STM32 HAL库):

/* Bootloader跳转到主固件 */
void jump_to_app(uint32_t app_addr)
{
    uint32_t stack_ptr = *(volatile uint32_t*)app_addr;      // 栈指针
    uint32_t reset_handler = *(volatile uint32_t*)(app_addr + 4); // 复位向量

    /* 关闭所有中断 */
    __disable_irq();

    /* 设置中断向量表偏移 */
    SCB->VTOR = app_addr;

    /* 设置主栈指针 */
    __set_MSP(stack_ptr);

    /* 跳转到主固件 */
    void (*app_entry)(void) = (void (*)(void))reset_handler;
    app_entry();
}

这段代码看着简单,但有几个坑:

  • 跳转前必须关中断,否则中断可能在跳转过程中触发。
  • 中断向量表偏移必须在跳转前设置好。
  • 主栈指针必须从固件头部读取,不能写死。

对于ESP32,启动流程稍有不同。ESP32的Bootloader是ROM固件,用户无法修改。它从Flash的0x1000地址读取分区表,然后根据分区表加载固件。ESP32支持OTA分区,可以同时存放两个固件版本。

总结一下:固件存储与启动,核心就三件事——校验、跳转、回滚。把这三点做好了,你的点钞机固件升级就成功了一半。

好了,第一章的内容就到这里。下一章我们聊聊点钞机的传感器驱动和信号处理——这部分才是点钞机的灵魂所在。