很多人第一次听说“GD32F103无缝替换STM32F103”这句话时都会下意识地觉得“无非就是下载个程序嘛能有多大事”。等你真把板子焊好、ST-Link接上、点下Download发现Keil报错或者程序根本不跑才会意识到这两个芯片的“无缝”主要体现在硬件管脚和软件接口上真正的坑全藏在启动配置、Flash参数和外设时序细节里。这篇文章就拿我自己从STM32F103RCT6切换到GD32F103RCT6的实际经历来写重点讲两件事第一ST-Link到底怎么把程序烧进GD32F103第二BOOT0引脚在烧录、复位、串口下载、IAP升级这些场景里是怎么一步步把人坑进去的。全程按实际操作的顺序来从接线到配置再到排查报错尽量给出一套可以直接照着做的流程。如果你正打算把手头的STM32项目迁到GD32F103或者已经画好了板子但烧录这步卡住了这篇文章应该能帮你省掉不少自己踩坑的时间。1. 为什么我会从STM32F103换到GD32F103先交代一下背景。我原来那个产品用的是STM32F103RCT6256KB Flash、48KB RAM基本够用。后来因为成本压力和供应周期的问题开始评估换到GD32F103RCT6。GD32F103系列是国产MCU里比较成熟的Cortex-M3方案硬件管脚基本和STM32F103对应型号Pin-to-Pin一致芯片本身也内置了兼容的调试接口所以第一反应就是“直接替换”。但直接替换的前提是你得搞清楚两个问题硬件上能不能直接焊接、直接供电、直接用同样的外围电路。软件上能不能用同样的开发环境、同样的烧录工具、同样的库函数跑起来。从硬件角度看绝大多数STM32F103最小系统板的外围电路比如晶振、复位电路、去耦电容、BOOT引脚上下拉GD32F103都能直接沿用。供电范围、GPIO耐压、ADC参考电压这些基础规格也基本对得上。从软件角度看GD32F103支持ARM Cortex-M3内核标准的SWD调试协议所以ST-Link这种调试器理论上是可以直接连上去的。Keil MDK里也不需要额外安装什么特殊插件只要选对Device型号、配置好调试器就能完成编译和下载。真正需要警惕的是那些“看起来兼容、实际上有差异”的地方。比如GD32F103的主频上限是108MHz而STM32F103只有72MHz比如两者的Flash等待周期配置不完全一致比如APB1/APB2时钟树的上限频率有差别还有一部分外设寄存器的复位值、标志位清除方式也不同。这些差异在简单工程里可能完全感觉不到一旦用到ADC、定时器、DMA、低功耗模式就要格外小心。2. 迁移之前必须搞清楚的兼容性底细2.1 管脚兼容是基础但不是全部我的验证板是直接拿STM32F103的PCB打样来测的没有改任何原理图管脚上确实完全兼容。GD32F103RCT6和STM32F103RCT6的封装都是LQFP64电源、地、晶振、BOOT0、BOOT1、NRST的位置完全一致。不过管脚一样不代表行为一样我实际遇到比较明显的一个差异是GPIO翻转速度。GD32F103的GPIO翻转速率理论上可以做到更高但在部分型号和部分电压条件下翻转沿的陡峭程度和STM32F103有明显区别。如果你的项目里有高速IO通信比如模拟SPI、模拟并口、DMA控制GPIO翻转需要实测确认时序是否满足要求。另一个容易被忽略的是内部上拉/下拉电阻的阻值范围。GD32F103的GPIO内部上下拉等效阻值约在30kΩ到50kΩ之间STM32F103则是一般在30kΩ到50kΩ的范围不同批次有差异如果把外部上拉电阻设计得特别大比如100kΩ以上两者表现就可能不一样。实际上多数场合没人在意这个但在低功耗或高阻抗输入场景里还是要实测一下。2.2 内核和外设模块的软件差异GD32F103和STM32F103都是Cortex-M3内核指令集一样中断向量表布局类似所以你的裸机代码、RTOS代码基本都能编译通过。标准外设库层面ST的SPL库和GD的Firmware Library函数命名很像但不能直接替换建议要么用寄存器方式重写关键外设驱动要么直接换成GD官方库。以USART为例GD32F103的USART时钟使能寄存器、波特率寄存器、状态标志位和STM32F103的布局是基本一致的用寄存器操作可以做到最小改动迁移。但GD32F103的USART输入时钟来自APB2APB2的最高频率可以到108MHz如果你沿用STM32F103里“72MHz主频、36MHz APB1、72MHz APB2”的假设波特率计算不会出问题但如果你把主频提到了108MHz就要重新算各个外设时钟分频。还有一个容易踩的是SysTick。SysTick是内核外设时钟源可以配置为内核时钟或外部参考时钟。GD32F103默认情况下内核时钟和SysTick的配置方式和STM32F103一致但如果你用延时函数的时候依赖“SystemCoreClock72MHz”这个全局变量换到GD32F103之后如果你的时钟初始化改成108MHz而SystemCoreClock没同步更新那delay就全乱了。2.3 Flash等待周期和选项字节的区别Flash等待周期这两个芯片有很关键的区别。STM32F103在72MHz主频以下通常配置2个等待周期就够了GD32F103的Flash设计不同官方要求在一定主频范围内配置对应的等待周期如果配置不对程序运行会出现随机死机或者取指错误。我之前在GD32F103上跑108MHz主频时用STM32F103默认的Flash等待周期配置程序在复杂运算时偶尔会进入HardFault。后来查了GD32参考手册发现108MHz下需要配置3个等待周期72MHz下则建议配置2个等待周期。这个必须按官方手册来不能照搬ST的习惯。还有选项字节GD32F103的选项字节地址和STM32F103基本一致但部分字节的含义、默认值、校验方式有差别。如果你用ST-Link工具去读GD32的选项字节可能读到一些奇怪的值不要慌张烧录的时候不要随便改写选项字节保持默认即可。3. ST-Link烧录GD32F103实操全流程3.1 接线和驱动准备ST-Link烧录GD32F103用的是SWD两线接口最低限度只需要接三根线SWDIO数据线对应PA13。SWCLK时钟线对应PA14。GND地线。如果目标板需要调试器供电可以再接一根3.3V如果目标板自己供电就不用接。实测下来GD32F103的SWD接口和STM32F103一样支持热连接但强烈建议先接好线再上电避免在连接过程中出现电平冲突。驱动方面ST-Link V2用ST官方的ST-Link USB Driver安装完Keil MDK之后一般会自动装好。如果设备管理器里看不到ST-Link而是出现未知设备手动安装一下驱动就行。V3版本的ST-Link也向下兼容SWD。3.2 Keil MDK里的配置细节在Keil里新建或打开GD32F103工程之后需要确认以下配置Options for Target - Device选择GD32F103系列对应型号或者选择Generic Cortex-M3 Device。如果你用的是GD官方Pack可以直接选具体型号如果没有退而求其次选Generic CM3也可以但这种情况要确认启动文件里的向量表大小是否正确。Options for Target - Debug右侧下拉框选择ST-Link Debugger然后点Settings。Settings里确认Port选SWMax Clock可以选4MHz或1.8MHz如果线比较长或干扰比较大降速能提高连接成功率。Flash Download页面点Add选择对应容量大小的Flash算法。比如RCT6是256KB选GD32F103的256KB Flash算法如果没有也可以手动选择STM32F103的算法很多情况下能用但擦写时序不保证100%可靠。我之前在Debug页面看到“No ULINK Device”或者“Cannot access target”这种报错多半是配置不对或者硬件没连好。3.3 用STM32 ST-LINK Utility烧录独立hex文件有时候你不想打开Keil只想把编译好的hex文件直接烧进芯片用STM32 ST-LINK Utility是最方便的办法。这个工具虽然是ST官方出品的但它基于ST-Link的SWD协议来访问芯片GD32F103也支持SWD所以可以正常使用。操作步骤很简单打开STM32 ST-LINK Utility。点击Target - Connect如果Target voltage显示有3.3V左右说明连接成功。点击File - Open file选你的hex文件。点击Target - Program确认起始地址是0x08000000点Start。烧录完成后再点Target - Verify确认数据已写入。这个工具还可以做整片擦除、读回Flash内容、修改选项字节但用的时候非常不建议乱动选项字节GD32的选项字节有一些保留位和ST不一样改坏了可能会锁死调试端口。如果真的不小心把SWD口锁了可以通过BOOT0拉高、进入系统存储器模式用串口ISP重新擦除后面会单独讲。3.4 烧录报错和排查思路这里整理一份我在实际使用中遇到的报错对照表现象可能原因排查步骤提示No target connectedSWDIO/SWCLK接反或虚焊量一下线序确认SWDIO接PA13、SWCLK接PA14提示Cannot access target目标板没有上电确认SWD接口的参考电压正常ST-Link能检测到3.3V烧录时卡在EraseFlash算法选错换匹配容量的Flash算法或者改用GD官方Pack里的算法烧录成功但程序不运行BOOT0为高复位后进Bootloader把BOOT0拉低复位重启烧录后跑飞或HardFaultFlash等待周期不对检查RCC配置和Flash等待周期提示RDDI-DAP ErrorSWD时序不稳或调试器供电不足降低SWD速率检查供电线径校验失败芯片Flash不是全空算法不匹配先做整片擦除再烧录这张表里的每一项都是我实际踩过的尤其是“烧录成功但程序不运行”十个里面有八个问题都出在BOOT0上。下一章专门讲BOOT0。4. BOOT0避坑指南烧录之后为什么不跑4.1 BOOT0到底是干嘛的BOOT0不是烧录用的引脚而是启动模式选择引脚。STM32F103和GD32F103都有BOOT0和BOOT1两个引脚它们的组合决定了芯片复位后从哪块存储空间开始执行。BOOT0BOOT1启动区域说明0x主Flash0x08000000正常运行用户程序10系统存储器0x1FFFF000内置Bootloader可用于串口ISP下载11SRAM0x20000000从RAM启动用于调试一般不常用注意BOOT1在LQFP64封装里对应PB2引脚。如果你把PB2当普通GPIO用同时又希望系统能从Flash启动只要BOOT0为0BOOT1无论是高是低都不影响。4.2 用ST-Link烧录时BOOT0该不该拉高答案非常明确SWD烧录完全不需要BOOT0参与BOOT0随便接什么电平都不会影响SWD识别芯片。这是因为SWD是内核调试接口只要芯片有供电、复位释放、SWD引脚没有被复用成普通IO调试器就能连上。那为什么很多教程反复强调“BOOT0一定要拉低”因为烧录完之后芯片复位如果BOOT0是高电平且BOOT1为低芯片会进入系统存储器Bootloader而不会运行你烧好的用户程序。表现出来就是“Keil提示烧录成功Flash里数据也校验过了但复位后什么都没发生程序完全不跑”。所以正确做法是正常开发板把BOOT0默认拉低用ST-Link烧录烧录完成后复位程序从Flash启动。如果你把BOOT0设计成可跳线切换那平时也记得跳回低电平。4.3 串口ISP下载和IAP升级时的BOOT0策略如果你用串口下载固件也就是通过USART1接USB转TTL模块用内置Bootloader下载程序那么BOOT0必须为高BOOT1为低复位后进入系统存储器Bootloader然后用厂家提供的串口ISP工具发送程序数据。GD32F103的系统存储器Bootloader支持串口和USB但具体协议和ST不是完全一样最好用GD官方的MCU ISP工具不要拿ST的Flash Loader硬试。如果你要做IAP升级也就是App自己通过串口、CAN或者网络接收新固件并写入Flash那么BOOT0始终保持为低。IAP的思路是上电从用户Boot区启动Boot区程序判断是否需要升级如果需要升级就接收数据并写入App区升级完成后跳转到App区执行。整个过程由用户程序自己控制不再依赖硬件BOOT0跳线。这里有个特别容易踩的坑IAP跳转到App之前必须重新设置栈指针MSP也就是从App区开头读取初始SP值并写入当前SP再从App区开头偏移4字节处读取复位向量地址然后跳转。如果你跳转前忘了关中断、忘了设置SP进App之后很快就会HardFault或跑飞。4.4 硬件设计上BOOT0怎么处理很多开发板会把BOOT0做成跳帽方便切换串口下载模式。但如果你做的是批量产品不想让产线工人去拨跳线建议直接把BOOT0通过10kΩ电阻下拉到地把BOOT1悬空或上拉到地都行。这样芯片默认从Flash启动产线烧录用SWD口直接烧完全不需要占BOOT0。如果你既要SWD烧录又想保留串口ISP升级通道也可以把BOOT0引到一个测试点或者通过0Ω电阻连接产线需要串口下载时焊上0Ω电阻平时不焊。还有一点BOOT0引脚内部没有很强的上下拉悬空状态是不确定的所以一定要有外部电阻确定电平。我看到过有人画板子把BOOT0故意悬空结果芯片一批能跑一批不能跑查了半天才发现是悬空导致启动模式不定。5. 实际迁移中的几个典型问题和解决办法5.1 老工程直接改芯片型号后编译出一堆警告如果你原来用的是STM32标准外设库想让工程直接改Device型号为GD32F103然后编译大概率会遇到找不到头文件、函数声明冲突等问题。因为ST的标准外设库文件路径和宏定义都是围绕STM32组织的GD32官方库的结构虽然有类似之处但很多文件名和函数名有差异直接套用会非常痛苦。我的建议是不要把整个老工程里的ST库函数当作黑盒直接“换芯”而是把你自己写的业务逻辑代码保留下来外设驱动层重新对着GD32官方例程改一遍。比如GPIO初始化、USART初始化、定时器PWM配置这些GD32的库函数风格和ST很像对照着改不需要太多时间。如果你用的是寄存器操作那就更简单了。GD32F103的大多数寄存器位定义和STM32F103一致个别寄存器比如RCC_CFGR里的PLL倍频位、Flash等待周期寄存器里的字段位置需要仔细查手册核对。5.2 延时函数突然不准了这个问题我在迁移的第2天就遇到了。我原来用SysTick做毫秒延时代码里写的是SystemCoreClock / 1000。迁移到GD32F103之后如果我在时钟初始化里把主频调到了108MHz而SystemCoreClock全局变量没有同步改成108000000那么延时就变成了原来的2/3串口时序全都乱了。排查方法很简单调试时看SystemCoreClock的值再对比实际主频配置即可。还有一种做法是不要用全局变量直接在延时函数里从寄存器读取系统时钟配置来计算这样无论你怎么改主频延时时间一定是对的。5.3 低功耗模式掉电电流偏大GD32F103和STM32F103在低功耗模式下的电流表现有一些差异。我在进入Stop模式后测待机电流发现GD32F103比STM32F103偏高一点点但还在可接受范围内。如果你的产品对休眠电流要求特别严格建议不要直接沿用ST的低功耗配置而是按GD32数据手册里的典型值重新估算。另外GD32F103退出Stop模式的唤醒源配置和STM32F103类似但部分外部中断唤醒时的触发沿配置需要注意。如果你之前在STM32F103上是“任意电平唤醒”在GD32上可能需要改成“上升沿”或“下降沿”唤醒否则可能唤醒不了。5.4 用AMS1117配陶瓷电容的问题有一个相关的硬件小问题顺带说一下多见于网上有人问“AMS1117输出端钽电容换成陶瓷电容对STM32有没有影响”。AMS1117这类低压差线性稳压器对输出电容的ESR有一定要求老的AMS1117用陶瓷电容尤其容量太小的时候环路稳定性容易出问题表现在输出电压振荡或者负载突变时压降异常。换成GD32F103之后芯片本身对供电稳定性的要求并没有更苛刻但如果你把输出端电容从100μF钽电容换成10μF陶瓷电容建议在AMS1117的输出端保留一个1Ω左右的串联电阻或者并联一个小的钽电容避免环路振荡。这个问题和芯片无关是电源芯片自身的问题但很多人在做GD32最小系统板时顺便把电容换了结果整体稳定性下降误以为是GD32的锅。5.5 RTC32.768kHz晶振起振慢或不起振GD32F103的RTC晶振起振电路和STM32F103类似但由于芯片内部振荡器电路参数不同对晶振的负载电容要求可能不同。我实测用同样的一颗32.768kHz晶振和12pF负载电容STM32F103能稳定起振GD32F103偶尔起振很慢甚至要手动碰一下晶振引脚才起振。解决办法在晶振两端并联一个1MΩ到10MΩ的反馈电阻或者增大负载电容到15pF左右试试。调整之后GD32F103的RTC起振就稳定多了。如果产品对RTC走时精度要求高建议用外部RTC芯片或者带有温度补偿的晶振不依赖MCU内部振荡器。6. 从STM32F103迁移到GD32F103的完整检查清单前面写了不少细节这里整理成一份可以直接对照的检查清单方便你在实际项目中逐项打勾确认。6.1 硬件检查清单确认GD32F103型号的封装、管脚顺序和原STM32F103完全一致。确认供电电压范围GD32F103一般支持2.0V到3.6V和STM32F103基本一致。确认BOOT0有外部下拉电阻上电默认从Flash启动。确认SWD接口的SWDIO和SWCLK没有被复用为普通IO。如果程序一开始就把PA13/PA14配置成GPIO或其它外设会直接导致烧录失败。如果用内部RC振荡器确认GD32的HSI频率是8MHz和STM32F103一致。如果用外部晶振确认晶振频率在GD32F103支持的范围内并注意匹配负载电容。如果板上有复位芯片确认复位引脚低电平有效复位时间满足芯片要求。6.2 软件检查清单确认Keil MDK里Device型号选择正确或至少选择Generic Cortex-M3 Device。确认启动文件选择的是Cortex-M3标准启动文件内部Flash容量和RAM容量要与型号匹配。确认SystemCoreClock全局变量与实际主频一致。确认Flash等待周期按GD32手册配置。确认APB1和APB2分频后的外设时钟频率没有超过外设上限。确认使用的外设库是GD32官方库而不是ST库。确认中断向量表地址在Bootloader和App跳转场景下配置正确。确认串口波特率按实际时钟重新计算不要沿用STM32的初始值。确认ADC采样时间和转换时钟频率在GD32规格范围内。确认低功耗模式唤醒源配置与GD32一致。6.3 产线烧录检查清单确认产线烧录使用的是SWD接口ST-Link或兼容的DAP-Link都可以。确认烧录时BOOT0保持低电平。确认烧录完成后执行一次复位并检查GPIO状态或串口打印确认程序在跑。如果产线用串口ISP下载确认BOOT0拉高BOOT1拉低并使用GD官方ISP工具。如果产品需要序列号或MAC地址确认烧录后是否需要在产线写入备份区。建议烧录完成后做一次Flash校验防止烧录中断导致固件损坏。7. 个人经验总结这篇内容从硬件兼容性、软件差异、ST-Link烧录流程、BOOT0启动模式到产线检查清单算是把STM32F103迁移到GD32F103的完整过程梳理了一遍。如果只让我留一句话给后来人那就是不要把GD32F103当成“一模一样”的STM32F103来用而要把GD32F103当成“管脚兼容、寄存器大部分兼容但需要重新验证”的新芯片来对待。只要心里有这句话很多坑其实都能提前避开。烧录层面的问题相对简单ST-Link配合SWD协议在GD32F103上完全够用。真正花时间的往往是BOOT0配置、Flash等待周期、外设时钟分频、低功耗唤醒这几个看起来不起眼的小地方。项目越复杂这些小差异被放大后造成的现象越离奇排查起来也越让人头疼。我自己的做法是在迁移初期专门做一块“芯片兼容性验证板”把MCU最小系统、USART、I2C、SPI、ADC、定时器PWM、RTC、低功耗唤醒、SWD接口全部引出来用板载跳线自由切换BOOT0模式。然后对着GD32官方例程逐个外设跑一遍每个外设都做半天以上的老化测试确认稳定后才把外围功能往上叠。这样下来后续产品量产时的返修率会低很多。最后再分享一个实用小技巧GD32F103的SWD接口默认是开启的但如果你在程序里不小心把PA13和PA14配成了普通GPIOSWD就断开了以后就没法用调试器连接了。遇到这种情况不要慌把BOOT0拉高复位进入系统存储器模式SWD接口会重新开放或者直接用串口ISP整片擦除后再恢复正常调试。这个特性在STM32F103上同样适用算是两个芯片都比较友好的地方。
企业数字化 ERP 产品动态
相关推荐
BK7259无线MCU:AI IPC场景下的低功耗芯片架构与实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 11:33:26
非接触式生命体征监测技术解析:从雷达到rPPG的选型与落地实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 11:33:19
2026年AI编码工具实战:6款神器提升开发效率 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 11:33:19
使用 AWS SDK for C++ 调用 AWS STS:AssumeRole 临时凭证示例详解 使用 AWS SDK for C 调用 AWS STS:AssumeRole 临时凭证示例详解 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For… · 2026/9/24 16:31:45
Jev专题:Jev在科学决策点能顶替大模型吗?选错关系却算出正确标签怎么办 (1)《三年面试五年模拟》AIGC / LLM / AI Agent 算法工程师与开发工程师求职面试秘籍,独家资源见 WeThinkIn/AIGC-Interview-Book,欢迎 Star! (2)AIGC / LLM / AI Agent 算法岗与开发岗求职面试… · 2026/9/24 16:31:45
@arizeai/phoenix-evals:用 TypeScript 构建 LLM 评估器与分类指标评估体系 可观测性AI 评测LLMOpsAI 应用人工智能 【免费下载链接】phoenix AI Observability & Evaluation 项目地址: https://gitcode.com/gh_mirrors/phoenix13/phoenix 点击查看 免费下载 本指南围绕 Phoenix 开源仓库中的 TypeScript 评估库 arizeai/phoenix-evals&… · 2026/9/24 16:31:45
GitHub Copilot for Xcode 自定义指令 如何上手 GitHub Copilot for Xcode 自定义指令 如何上手 【免费下载链接】CopilotForXcode AI coding assistant for Xcode 项目地址: https://gitcode.com/GitHub_Trending/cop/CopilotForXcode
想让 AI 按你的规范写代码,却每次都在提示词里重复塞"命名约定、… · 2026/9/24 16:31:34
两条路给AI Agent接酒店能力:OTA API vs 供应链直连,我替你踩了所有坑 两条路给AI Agent接酒店能力:OTA API vs 供应链直连,我替你踩了所有坑
最近三个月,市面上有一个酒旅方向的AI Agent,核心功能之一就是让用户在对话里完成酒店搜索和预订。
听起来不复杂——找个酒店API接上不就完了?实… · 2026/9/24 16:31:34
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44