☰
STM32F103RCT6最小系统板设计制作全流程:从原理图到MDK配置
2026/10/3 8:06:27 网站建设 项目流程

前一阵把手上的STM32F103RCT6核心板焊完、调通,前后折腾了差不多一个周末。这板子是我给自己做的第3块最小系统板,前面两块分别是C8T6和F407VET6,这次换成RCT6,图的就是它256KB Flash和48KB SRAM,跑一些稍微复杂点的逻辑、日志缓冲、字库缓存都宽松很多。这篇文章把这次从原理图设计、PCB打样、手工焊接,到MDK工程配置、固件库移植、SWD下载调试的完整过程捋一遍。网上关于C8T6最小系统的资料已经多到溢出来了,但RCT6在引脚封装、启动配置、Flash容量差异上还是有一些小坑,这篇文章重点讲这部分,给也想自己画板子、不想一直用开发板的同学做一个参考。

说句实在话,最早玩STM32的时候我也直接买现成的核心板,几十块钱还带USB转串口,省事是真省事。但玩到后面你会发现,核心板上的引脚引出、电源布局、晶振位置不一定符合你自己的项目需要,尤其是做电机驱动、传感器阵列、带LCD显示屏这类东西的时候,接口位置乱、走线绕、还得飞线,特别难受。

自己做一块最小系统板,核心价值不是省钱,而是“知道自己这块板子的每一根走线是怎么走的、每个电容是干什么用的”,后续在外围电路上翻车的时候排查起来会非常快。这篇文章的核心就是记录这块STM32F103RCT6最小系统板从设计到配置的全过程,重点在MCU配置环节,包括Keil工程怎么建、固件库怎么选、下载器怎么配、常见报错怎么解。

1. 整体设计与方案选型

1.1 为什么是RCT6而不是C8T6或者RBT6

先看一颗料怎么选。STM32F103系列里大家用得最多的是C8T6,48脚,64KB Flash,20KB SRAM。做个小车、点个灯、跑个逻辑控制完全够用,而且价格便宜、资料满天飞。但这几年随着屏幕、传感器、通信协议栈往项目里越塞越多,64KB Flash真的有点吃紧。我上一个用C8T6的项目,光UI界面加中文字库就占掉了差不多40KB Flash,再塞协议解析、日志存储就开始扣扣搜搜了。

RCT6同样是LQFP64封装,引脚兼容RB、RC、RD、RE这一整个家族,只是Flash和SRAM容量不同。RCT6是256KB Flash、48KB SRAM,主频还是72MHz,Cortex-M3内核。比RBT6(128KB Flash/20KB SRAM)容量翻倍,价格也就贵几块钱,性价比很高。

引脚兼容这个点太重要了。如果你之前用的是C8T6(LQFP48),要换RCT6还得重新画板子。但如果像我这次一样直接从设计阶段就选LQFP64封装,以后想升级到RE(512KB)或者降级到RB,只需要换芯片,板子不用动。底板和核心板分离的设计思路也是这个道理,核心板定义好接口,底板按项目需要自己画,迭代速度快很多。

1.2 最小系统板到底“最小”到什么程度

很多初学者对“最小系统”的理解就是芯片加电源、加晶振、加复位,能跑起来就行。这个理解对吧?对,但不完全。

STM32F103RCT6要真正稳定运行,至少需要这几块:

  • 电源系统:3.3V供电,每个电源引脚都要就近放置100nF去耦电容,芯片旁边再放大容量的钽电容或电解电容做低频滤波。
  • 时钟系统:8MHz主晶振加两个负载电容,还有32.768kHz的RTC晶振(如果用到RTC或者低功耗唤醒就需要)。
  • 复位电路:NRST引脚上拉电阻加对地电容,经典配置是10kΩ上拉加100nF电容。
  • 启动配置:BOOT0和BOOT1引脚的电平设置,决定芯片从哪里启动。
  • 下载调试接口:SWD四线(SWDIO、SWCLK、GND、3.3V)足够用,建议把NRST也引出来。
  • 去耦和滤波:这个最容易忽略但又最致命。

我这次做的板子除了这些最小必须项,还额外加了电源指示灯、用户LED、一键复位按键、USB转串口预留接口,算是一个“实用型最小系统板”。不加这些也能跑,但调试的时候有颗LED真的方便太多。当然,板子引出的排针尽量把所有IO都引出来,方便后续飞线或者插底板。

1.3 供电方案选型:LDO还是DCDC

最小系统板的输入电源一般有两个来源:USB的5V,或者外部直流电源。我这次把两种都做了兼容:板载一个USB Micro接口,同时留了一个5V和GND的焊盘,方便外接电源。

5V转3.3V的方案纠结了一下。用DCDC效率高但外围器件多,电感选型也讲究,在最小系统板上属于过度设计。板子整体电流不大,LDO完全够用还安静,纹波也干净,对ADC采样友好。我选的是AMS1117-3.3,便宜大碗,手册上写着最大1A输出,实际稳定输出500mA没问题,驱动传感器、OLED、小屏这类外设够了。如果后续外设功耗大,可以换成RT9193或者ME6211这类低压差LDO,压差更低、纹波更小,但引脚不兼容,得改板子。

对了,AMS1117输入输出端都要加电容。输入端并10μF钽电容和100nF陶瓷电容,输出端并22μF和100nF,具体取值看手册推荐值,别偷懒,这些电容直接影响电源稳定性。

2. 硬件设计核心细节解析

2.1 电源引脚的每个电容都有讲究

STM32的数据手册上写得很明白:每个VDD引脚需要接一个100nF的陶瓷电容,且尽量靠近引脚放置。RCT6有4个VDD引脚加1个VDDA,加上VREF+,数下来要在芯片周围摆7~8个100nF电容。

很多人画板子的时候觉得电容多,随手放几个就算完事。实际上高频去耦电容的位置比容值更重要。如果电容离引脚太远,走线电感会抵消掉电容的高频滤波效果,等于白放。我的做法是LQFP64芯片四周均匀布置100nF 0402电容,每个VDD或VDDA旁边都有就近的电容位。这个细节在你用电烙铁飞线调试的时候感觉不出来,但遇到莫名其妙的复位重启、ADC采样毛刺大的时候,回来检查电源去耦绝对有收获。

大容量储能电容方面,我放了两个:一个47μF钽电容放在板子电源入口处,负责整个板子的低频储能;一个10μF陶瓷电容放在芯片电源输入附近。为什么不用两个大电解?因为储能电容需要容值大,但不同容值的电容谐振频率不同,小容值陶瓷电容高频特性好,大容值电解/钽电容低频储能强,两者搭配效果最好。

2.2 主晶振电路参数怎么定

8MHz晶振配两个负载电容,这个电路看着简单,但参数选错了会导致晶振起振困难、频率偏大偏小,甚至完全不起振。

晶振的负载电容参数取决于晶振自身的规格。以我用的这颗8MHz无源晶振为例,规格书上写着负载电容CL=20pF,那么两个谐振电容取值要满足CL=(C1*C2)/(C1+C2)+寄生电容的经验公式。通常两个电容取相同值,假设寄生电容约5pF,则C1=C2约为30pF。但实际设计中直接按晶振厂商推荐的20pF~22pF来取值也问题不大,因为STM32内部有集成反馈电阻,外部不并联1MΩ电阻也能起振,只是加上更保险。

这里说一个大坑:晶振旁边要走地线隔离,不要和高速数字信号线贴着走。我有一次画板子为了省空间,把SCL时钟线和晶振线并行走了一段,结果I2C通信偶尔卡死、主频异常,后来把晶振下方铺地、把走线拉开才解决。晶振电路周围铺一圈地铜,对稳定性提升非常明显。

2.3 复位电路和启动模式配置

NRST引脚上拉10kΩ到3.3V,对地接100nF电容,按下按键时拉低复位,松开后电容充电延时复位释放,防止按键抖动。这个是教科书电路,照抄就行。

BOOT0和BOOT1的处理,很多开发板直接用一个跳线帽或者拨码开关来切换。我这次用的方式是在引脚上各焊一个10kΩ下拉电阻,默认都是低电平,即从主Flash启动,正常跑用户程序。如果有人想要串口ISP下载,只需要把BOOT0飞线短接到3.3V上再复位一下就行。

特别注意BOOT0不能悬空。悬空状态下引脚电平不确定,有可能导致芯片启动到系统存储器(BootLoader)而不是用户Flash,表现为程序烧不进去或者上电不运行。这个坑我见过很多新手踩,排查的时候先量BOOT0电平。

2.4 SWD下载接口与JTAG取舍

下载调试接口我强烈建议用SWD,四根线搞定:SWDIO、SWCLK、GND、3.3V。如果用手头的ST-Link V2,连上这四根线就能下载和在线仿真。JTAG需要5根线还占用的IO多,而且是20Pin标准接口,在最小系统板上太占地方。

但有几个细节值得注意。SWDIO和SWCLK是PA13和PA14,它们默认就是SWD功能,但如果用户代码里面把这两个引脚复用成了GPIO,下次下载就会失败。解决办法是烧录时按住复位键,点击下载,在开始下载瞬间松开复位键,让芯片在复位状态下进入下载流程。ST-Link可以在MDK里勾选“Reset and Run”,这样每次下载后自动复位运行。

另外建议把NRST也引到下载接口。SWD协议里不接NRST也能下载,但如果你在程序里禁用了SWD引脚,就只能通过NRST硬件复位的方式配合下载器找回烧录口。我在板子上引了5Pin的SWD排针:3V3、SWDIO、SWCLK、GND、NRST,调试的时候非常方便,不用每次重新插拔。

3. PCB布局与手工焊接实操

3.1 LQFP64的布局要点

LQFP64封装是0.5mm引脚间距,引脚密,布局的时候最忌讳把电容放得太远。我的布局思路是:

  • 芯片居中,四边留出走线通道和去耦电容位置。
  • 100nF去耦电容统一放在芯片背面对应电源引脚的位置(需要开过孔)或者正面靠近引脚的地方,保证走线尽可能短。
  • 8MHz晶振放在芯片旁边,远离板边和功率器件,晶振正下方铺地并打过孔阵列。
  • 排针接口分布在板子两侧,方便搭面包板和插底板。
  • 电源入口、LDO、储能电容放在一角,和芯片之间用地隔离。

布局这东西没有绝对标准,但核心原则只有一个:高频和敏感信号线越短越好,电源路径越宽越好,大电流回路不要和小信号回路共用一段走线。

电源走线我加了加粗处理,默认信号线是0.25mm,电源主干线改成0.8mm,3.3V这条网络尽量整板铺铜,降低压降和地弹噪声。铺铜间隙设小一点,避免细长的地线孤岛。

3.2 手工焊接LQFP64的经验

0.5mm间距的LQFP64芯片,手工焊接对新手来说是比较有挑战的一件事,但掌握了方法其实难度没那么大。

我的焊接流程供参考:先在焊盘上均匀上一层薄锡,再把芯片对准方向放上去,对齐所有引脚后用焊锡将四个角固定。然后从一个角开始,把焊锡丝压在引脚上,让熔化的焊锡自然覆盖引脚和焊盘,一整排拖过去。引脚多、间距小,直接拖焊容易连锡,所以拖完后要用吸锡带清理多余焊锡。吸锡带配助焊剂,效果立竿见影,引脚之间干干净净。

焊完先别急着上电,用万用表蜂鸣档检查相邻引脚有没有短路,重点是VDD和GND之间不要短路。LQFP64有4个VDD和4个VSS,任意一组短接都会导致上电烧板。这个步骤不能省,宁可检查三遍也不要上电冒烟。

3.3 首次上电检查流程

焊接完到烧录之前,建议按下面的顺序做检查:

  1. 用放大镜或手机微距镜头检查所有引脚是否有虚焊、连锡。
  2. 万用表蜂鸣档测VDD和GND之间是否短路,正常应该是开路或有大电容充电的滴一声后断开。
  3. 不插芯片或者不焊芯片的情况下先给板子供电,量3.3V输出是否正常。
  4. 确认3.3V正常后,再焊芯片,重新测一次VDD/GND。
  5. 用示波器(没有的话用万用表频率档)检查8MHz晶振两个引脚是否有振荡波形,正常起振后电压约在1.6V~1.9V之间波动。

我第一次自己做板子的时候,第2步没认真做,直接上电,结果AMS1117发烫,一查发现芯片焊接时有个引脚连锡把3.3V和地短在了一起。从那以后,每次焊接完上电前我都会老老实实测一遍电源对地阻抗。这个习惯救过我好几次板子。

4. MCU固件配置与下载调试环境搭建

4.1 MDK工程搭建与芯片型号选择

硬件焊接完成,进入“MCU配置”这个主题。首先是搭建开发环境。我用的是Keil MDK 5.x,装好以后第一件事是在Pack Installer里安装STM32F1系列的Device Family Pack。如果装过F4的开发环境,也要确认F1的包在,因为F1和F4是不同的Pack。

新建工程的时候,Device选型要选对。很多人用的习惯是在搜索框输入“STM32F103RC”,然后选了“STM32F103RC”而不是“STM32F103RCT6”,这在MDK里是同一个选项,因为MDK的Device列表是按型号族归类的,选了STM32F103RC就包含了RCT6。但如果你选了“STM32F103RB”,最终生成的Flash算法和链接脚本就会按128KB来,程序超过128KB就链接报错,这是个隐蔽问题。

这里特别提醒一下:MDK工程建立时选择Device后会自动配置好相应的芯片型号,但你必须手工确认Output选项卡里“Create HEX File”有没有勾选。如果你需要生成HEX文件烧录到芯片,这一步不能漏,我在新手阶段就因为这个勾没打上,整了半天生成的HEX文件。

4.2 固件库包选择:标准外设库还是HAL库

STM32F103这一代芯片的开发方式有三种主流选择:寄存器直接操作、标准外设库(StdPeriph)、HAL库(配合CubeMX生成代码)。

我的建议是:如果是从零学起,直接学HAL库也没什么问题,STM32CubeMX生成初始化代码效率高,F1系列也支持得很好。但如果你手上有很多老项目的代码、例程,都是基于标准外设库写的,那用标准外设库也不丢人。我这次用的是标准外设库V3.5,理由很实在:一是我手头的RCT6固件库包和例程都是这个版本,二是我要移植之前项目的代码,标准库兼容起来更省事。

标准和HAL之争这里不展开,只提一点:STM32F103标准外设库在MDK工程里需要在C/C++选项卡的Define里加两个宏:USE_STDPERIPH_DRIVER和STM32F10X_HD。第一个宏是告诉编译器启用外设驱动库,第二个是告诉编译器当前芯片属于高密度器件(RCT6的Flash是256KB,属于高密度类别,对应ST芯片密度分类中HD)。如果你漏了STM32F10X_HD这个宏,编译的时候极大概率会报错或者链接异常,因为库内部很多条件编译是根据这个宏来展开的。

4.3 标准外设库工程结构

我这里把RCT6的工程目录结构列出来,照着建就行,不用过度纠结:

Project/ ├─ User/ main.c、stm32f10x_it.c、system_stm32f10x.c ├─ Core/ startup_stm32f10x_hd.s(启动文件) ├─ Periph/ stm32f10x_conf.h、stm32f10x.h ├─ Periph/src/ stm32f10x_gpio.c、stm32f10x_rcc.c等外设库源文件 └─ Periph/inc/ 外设库头文件

启动文件必须用startup_stm32f10x_hd.s,而不是ld.s或者md.s。HD代表高密度,适用于Flash容量在256KB~512KB之间的F103器件,刚好覆盖RCT6。MD版本适用于中密度(64KB~128KB),如果选错,程序可能运行不正常甚至完全跑不起来。

4.4 ST-Link调试器配置与常见报错

接下来说调试器配置。MDK里点击魔法棒(Options for Target),切到Debug选项卡,右侧选择“ST-Link Debugger”,然后点旁边的Settings。这里要检查两个东西:一是右侧的“Flash Download”里选中的Programmer算法,必须是“STM32F10x High-density 256K Flash”;二是Reset策略建议选“Hardware Reset”(有些ST-Link固件可以在连接时自动复位目标芯片)。

最常见的三个报错分别说一下:

第一个是No Target Connected。这个基本上是接线问题,SWDIO、SWCLK、GND三根线必须接对,而且目标板要上电。注意ST-Link V2供电能力有限,如果目标板上有大电流外设,尽量单独供电,ST-Link只负责下载和调试,不要让它承担负载电流。

第二个是RDDI-DAP Error。这个报错通常是芯片进入了低功耗模式,或者SWD引脚被程序改成了普通GPIO。解决办法是按住板子上的复位键不放,点击下载,等MDK提示连接成功后立刻松开复位键。如果每次都这么麻烦,还有一个终极办法:把BOOT0拉高并复位进入BootLoader模式,用FlyMcu这类串口ISP工具清除Flash,之后SWD就能重新连上了。

第三个是Flash Download failed - Cortex-M3。这个一般是Flash算法选错了,去Utilities或者Flash Download里检查是不是选的High-density,或者芯片Flash被写保护了。写保护解除方式是用ST-Link Utility这类工具连接芯片,选择Option Bytes,把Write Protection级别改成Disabled,然后重新下载即可。

4.5 最小系统验证代码

配置完成后,先烧一个最小验证代码,确认芯片、晶振、下载链路都没问题。下面这段代码实现的功能是:PA0引脚配置为推挽输出,以500ms间隔翻转电平,用万用表或者LED观察波形。

#include "stm32f10x.h" void Delay(volatile uint32_t nCount) { while(nCount--) { } } int main(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while(1) { GPIO_SetBits(GPIOA, GPIO_Pin_0); Delay(7200000); GPIO_ResetBits(GPIOA, GPIO_Pin_0); Delay(7200000); } }

如果这段代码能正常让LED闪烁,说明最小系统板从硬件到软件全部打通了。Delay函数里7200000这个数字在72MHz主频下大约是100ms左右的延时,不做精确计时用,只是验证心跳。

这里补充一个易错点:MDK工程默认使用外部8MHz晶振作为系统时钟源,如果你板子上没焊晶振或者晶振没起振,程序会一直卡在SystemInit里面,表现出来就是程序下载成功但完全没反应。排查方法是直接在调试状态下全速运行,在SystemInit里设断点,看是不是卡在等待HSERDY标志位置位。要是卡住,优先查晶振电路和负载电容。

5. 常见问题与排查技巧实录

5.1 上电后芯片发热严重

芯片发热第一件事就是断电,然后量VDD和GND之间的阻抗。小于10Ω基本可以确定焊接短路。用万用表跟在引脚上逐一排查,或者借助热成像仪看发热点,没有热成像仪就把助焊剂洗干净后仔细观察有没有锡珠残留。0402的电容非常容易被锡珠桥接短路,焊完以后清理助焊剂要仔细。

5.2 晶振不起振

首先确认晶振是好的,换一颗试试。然后查负载电容是否虚焊,电容焊接不良会导致起振条件不满足。还可以在晶振两个引脚并联1MΩ电阻,加强反馈,帮助起振。另外检查晶振是否和旁边走线靠太近,这个在Layout阶段就要注意。

5.3 程序能下载但运行异常,主频感觉不对

如果你用的是标准外设库,检查system_stm32f10x.c里#define SYSCLK_FREQ_72MHz有没有打开。默认情况下如果定义的是SYSCLK_FREQ_8MHz或SYSCLK_FREQ_36MHz,程序能跑但外设时序全部错乱,串口波特率对不上、延时不准。这种情况不仔细看非常难排查。

5.4 SWD下载时好时坏

这个是接触不良居多。检查排针焊接质量,杜邦线是否松动。另外把SWD接线尽量缩短,线太长会增加信号反射,高速下载时容易失败。实在不行把MDK里SW Mode的Max Clock从4MHz降到1MHz试试,稳定性会好很多。

5.5 最小系统板vs开发板调试差异

最后说一句经验之谈:自己画的最小系统板,调试起来和买来的开发板最大的区别是少了板载的USB转串口,没有调试打印通道。我建议在底板或者外设板上预留一个USB转TTL模块接口(CH340或者CP2102都行),调试的时候插上去就能用串口打印。串口打印调试是嵌入式开发里效率最高的手段之一,没有这个口,出问题就得靠猜,板子再小也要把调试口留好。我自己画的核心板都预留了PA9、PA10、GND三根串口引脚,调试体验会舒服很多。

这块RCT6最小系统板目前已经被我用到了一个环境监测小项目上,跑着SHT30温湿度传感器加一个0.96寸OLED屏,256KB Flash随便造,代码写得再奔放也不用担心空间。回头再看,自己做最小系统板的意义其实是倒逼你把芯片的数据手册、电路设计、启动配置这些最基础的东西全部吃透。买来的核心板用一百次,你也不会知道BOOT0为什么要接下拉电阻,但自己画过一次,这些东西就长在脑子里了。

如果后续还想扩展,可以考虑在核心板上加一个SD卡座用来存日志,或者把这颗RCT6的FSMC接口用起来接一个TFTLCD屏幕,F103的FSMC驱动屏幕还是很流畅的,外扩SRAM也行。硬件这东西就是这样,板子做好了,后面能玩的路子就宽了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询