用Keil5实现STM32F103的串口ISP烧录:从原理到实战
你有没有遇到过这样的场景?产品已经出货,客户反馈需要升级固件,但板子上没有SWD接口;或者你在做一款紧凑型小设备,为了节省空间干脆没引出调试针脚。这时候,传统的ST-Link下载方式就彻底失效了。
别急——STM32F103自带“后门”:只要合理利用它的内置Bootloader和串口通信能力,哪怕没有调试器,也能完成程序烧录。而我们每天都在用的Keil5(MDK),虽然本身不支持串口下载,但稍加配置,就能让它“指挥”外部工具自动完成整个ISP流程。
本文将带你一步步打通这条“无编程器”的技术路径,真正实现:写完代码,一键编译+自动下载。
STM32F103的ISP机制:芯片出厂就带的“救援系统”
每个STM32F103芯片在生产时,都会在系统存储区固化一段不可擦除的Bootloader程序。这段代码就像是MCU的“BIOS”,它不会随着你的应用代码被刷掉,永远存在。
启动模式由谁决定?
答案是两个引脚:BOOT0 和 BOOT1。它们的状态决定了芯片上电后从哪里开始执行:
| BOOT1 | BOOT0 | 启动区域 |
|---|---|---|
| X | 0 | 主闪存(Main Flash) → 正常运行用户程序 |
| 0 | 1 | 系统存储器(System Memory) → 进入ISP模式 |
| 1 | 1 | 内部SRAM |
✅ 所以关键来了:想进入ISP模式,必须让BOOT0 = 1,BOOT1 = 0。
一旦满足这个条件并复位芯片,MCU就会跳转到内部Bootloader,并自动初始化USART1(PA9/TX, PA10/RX),波特率通常为115200bps(支持自适应检测),然后等待主机发送同步字符0x7F。
Bootloader能做什么?
通过标准的STM32 USART通信协议,你可以对芯片执行以下操作:
- ✅ 查询芯片ID、获取支持命令
- ✅ 擦除Flash(全片或指定扇区)
- ✅ 向Flash写入数据(按页编程)
- ✅ 读取内存内容进行校验
- ✅ 下载完成后跳转到用户程序运行
整个过程只需要一根USB转TTL线(3.3V电平!),无需任何额外处理器或复杂协议栈。
⚠️ 注意事项:
- 通信必须使用TTL电平(不是RS232!)
- PA9/PA10不能有强干扰或负载
- 烧录期间严禁断电,否则可能变砖
- 不支持调试功能(断点、单步等)
Keil5如何参与ISP?真相是:它只负责“编译”,别人来“烧”
很多人误以为Keil5可以直接通过串口下载程序,其实不然。Keil5原生仅支持JTAG/SWD接口(如ST-Link、J-Link)进行Flash编程。
但我们可以通过一个巧妙的方式绕过限制:把Keil5当作前端编译器,生成.bin文件后,调用外部ISP工具自动完成下载。
这就像你写好Word文档,点击“打印”按钮,系统自动调用打印机驱动一样——Keil5点“Download”,背后跑的是stm32flash这类工具。
实现思路一句话总结:
编译成功 → 生成BIN文件 → 触发脚本 → 外部工具通过串口下载
这样一来,开发体验几乎和直接下载一模一样,只是底层换成了串口通信。
手把手教你配置Keil5 + stm32flash 实现一键ISP
下面我们以Windows平台为例,使用开源工具stm32flash完成集成。
第一步:安装stm32flash工具
Windows用户:
前往 https://sourceforge.net/projects/stm32flash/ 下载预编译的.exe文件,解压后将stm32flash.exe放入项目目录或添加到系统PATH。
Linux用户(顺带提一句):
sudo apt-get install stm32flash第二步:编写自动化烧录脚本isp_download.bat
创建一个批处理文件,用于接收参数并执行下载命令:
@echo off REM ========================================== REM STM32F103 ISP烧录脚本 REM 调用方式: isp_download.bat COM3 .\Objects\project.bin REM ========================================== set PORT=%1 set FILE=%2 echo. echo ************************************************** echo 即将通过串口 %PORT% 烧录固件... echo 固件路径: %FILE% echo ************************************************** echo. echo 请确保: echo 1. BOOT0 = 高电平 (接VCC) echo 2. BOOT1 = 低电平 (接地) echo 3. USB-TTL已正确连接 (TX→PA10, RX→PA9) echo 4. 芯片已上电或复位 echo. pause :: 开始烧录 stm32flash.exe -w "%FILE%" -v -g 0x8000000 -b 115200 %PORT% if %ERRORLEVEL% EQU 0 ( echo. echo [ SUCCESS ] ✅ 固件烧录并验证成功! echo MCU即将从0x8000000启动新程序。 ) else ( echo. echo [ FAILED ] ❌ 烧录失败,请检查连接、供电或重试。 ) echo. pause📌 关键参数说明:
-w:写入模式-v:写入后自动读回校验-g 0x8000000:下载完成后跳转至主Flash起始地址运行-b 115200:设置通信波特率%PORT%:COM端口号(如COM3)
第三步:Keil5中配置“构建后事件”
打开你的Keil项目,进入设置界面:
Project -> Options for Target -> User- 在“After Build/Rebuild”区域勾选 “Run #1”
- 输入以下命令:
cmd /c "isp_download.bat COM3 .\Objects\your_project.bin"🔧 替换说明:
-COM3→ 改为你电脑实际分配的串口号
-your_project.bin→ 改为你的输出文件名(一般与工程同名)
第四步:设置Keil输出格式为BIN
默认Keil生成的是HEX文件,我们需要改成BIN。
Options -> Output- 取消勾选Create HEX File
- 勾选Create Binary File
✅ 设置完成后,每次点击“Build”或“Download”,Keil都会先编译生成.bin文件,然后自动运行你写的脚本发起ISP下载。
实际工作流程拆解
现在我们完整走一遍从开发到烧录的全过程:
硬件准备
- 使用杜邦线连接USB-TTL模块:- TXD → PA10(STM32接收)
- RXD → PA9(STM32发送)
- GND → GND
- 将BOOT0接到VCC,BOOT1接地
- 上电或按下复位键
软件操作
- 在Keil中修改代码 → 编译(F7)
- 点击“Download”按钮
- 自动弹出CMD窗口,执行isp_download.bat
- 脚本调用stm32flash建立连接、擦除、写入、校验
- 成功后提示“烧录完成”,MCU自动跳转运行退出ISP模式
- 下次启动前,记得把BOOT0改回低电平(GND)
- 否则每次都会进入Bootloader,无法正常运行程序
常见问题与避坑指南
❓ 为什么总是连接失败?
最常见原因如下:
| 问题 | 检查项 |
|---|---|
| 🔄 未发送同步帧 | 确保工具发送了0x7F |
| 🔌 接线错误 | TX-RX要交叉接(PC-TX → MCU-RX) |
| ⚡ 电平不匹配 | 必须使用3.3V TTL,不能用5V或RS232 |
| 💣 BOOT引脚错误 | BOOT0必须为高,BOOT1为低 |
| 🧊 波特率偏差大 | 换成115200bps试试,避免使用非标速率 |
❓ 如何避免每次都要手动切换BOOT引脚?
可以在设计阶段加入一些“人性化”机制:
- 使用拨码开关控制BOOT0
- 或者用MCU GPIO配合按键实现“升级模式唤醒”:
c if (GPIO_ReadKey() == UPGRADE_KEY && time_hold > 3s) { jump_to_bootloader(); // 软件跳转至Bootloader }注:需保留Bootloader入口地址
0x1FFF0000并禁止优化
❓ 可以防止非法刷机吗?
当然可以,在量产环境中建议增加安全策略:
- 关闭ISP功能(通过选项字节禁用)
- 或在用户程序中增加认证机制(例如加密签名验证)
- 或只允许特定条件下进入ISP模式(如密码+物理按键组合)
为什么这套方案值得掌握?
尽管现在OTA很流行,但在很多真实工程场景中,串口ISP仍然是最可靠、最低成本的救急手段。
| 场景 | 价值体现 |
|---|---|
| 教学实验 | 学生动手门槛低,无需购买ST-Link |
| 小批量生产 | 节省编程器投入,降低产线成本 |
| 现场维护 | 技术人员带笔记本+串口线即可升级 |
| 极简设计 | 板子太小?没关系,留两个引脚就够了 |
| 快速原型 | 早期验证阶段,免去调试器依赖 |
更重要的是,理解这套机制后,你可以轻松将其扩展为更高级的功能:
- 结合ESP8266/WiFi模块 → 实现简易OTA
- 通过CAN总线远程触发ISP → 工业现场升级
- 利用RS485组网批量更新 → 多节点固件同步
写在最后:这不是过渡方案,而是必备技能
也许你会说:“我现在有ST-Link,干嘛要用这么麻烦的方法?”
但真正的嵌入式工程师都知道:当你最需要它的时候,往往正是你没有调试器的时候。
掌握Keil5与ISP的联动技巧,不只是学会一种烧录方式,更是建立起一套“无依赖部署”的思维模式。它是你面对突发状况时的最后一道防线,也是你设计更健壮系统的起点。
下次当你画PCB时,不妨多留一组TX/RX和一个BOOT0控制方式——说不定哪天,它就能帮你省下一次出差的成本。
如果你也在用类似的方法提升开发效率,欢迎在评论区分享你的实践心得。