第一章:课程导论与硬件基础
各位同学好,我是你们这门课的老张。做嵌入式开发十几年了,从最早的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:引导程序,负责检查固件、决定启动哪个版本。
- 主固件区:存放正常运行的程序。
- 备份固件区:存放上一个稳定版本,用于回滚。
启动流程大概是这样的:
- 上电后,芯片从0x08000000地址开始执行(这是STM32的Flash起始地址)。
- Bootloader先检查主固件区的CRC校验。如果校验通过,跳转到主固件。
- 如果校验失败(比如升级过程中断电了),Bootloader自动从备份区加载固件。
- 如果两个区都坏了...嗯,那就只能进厂返修了。
这里有个细节:中断向量表的重映射。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分区,可以同时存放两个固件版本。
总结一下:固件存储与启动,核心就三件事——校验、跳转、回滚。把这三点做好了,你的点钞机固件升级就成功了一半。
好了,第一章的内容就到这里。下一章我们聊聊点钞机的传感器驱动和信号处理——这部分才是点钞机的灵魂所在。