
1. 为什么一块最小系统板值得反复打磨STM32F103C8T6这颗料圈子里叫它蓝药丸或者最小系统板几乎是每个嵌入式工程师入门ARM Cortex-M3的第一块板子。它便宜、好买、资料多48个引脚塞进了72MHz主频、64KB Flash、20KB SRAM还有CAN、USB、多个USART和SPI性价比放到今天依然能打。但真正自己动手从原理图到PCB走一遍的人会发现这块板子看着简单坑却不少——电源纹波、晶振不起振、复位电路误触发、SWD下载失败、BOOT引脚配置错误随便一个都能让你在调试台上耗掉一整个下午。这篇内容就是把我自己画这块板子踩过的坑、验证过的方案、以及一些教科书上不会写的细节完整地摊开来讲。适合已经会基本EDA操作、想自己画一块能稳定跑起来的最小系统板的同学也适合画过几版但总有小毛病、想搞清楚为什么这么设计的工程师。核心关键词就三个STM32F103C8T6、最小系统核心板、原理图与PCB设计。我会从整体思路讲到具体参数计算再到实操步骤和排查技巧尽量做到你照着做就能复现。先说清楚一个前提最小系统不等于能点亮LED就行。一个合格的最小系统核心板至少要保证MCU能稳定上电、能可靠复位、能正常下载程序、晶振能起振、电源干净、BOOT模式可切换。这五条是底线任何一条出问题后面写再多代码都是白搭。所以设计的时候思路要围绕稳定性而不是能跑就行来展开。2. 整体方案设计与核心思路拆解2.1 最小系统的边界到底在哪里很多人对最小系统的理解有偏差以为只要把MCU焊上去、接个电源就行。实际上STM32F103C8T6要能正常工作外围必须包含这几块电源电路3.3V稳压、复位电路、时钟电路外部晶振、启动模式配置电路BOOT0/BOOT1、以及调试接口SWD。这五块缺一不可少一个都可能出现程序下载不进去或者上电不运行的情况。我见过有人为了省事把BOOT0直接接地、BOOT1也接地结果想用串口下载的时候发现进不去Bootloader只能拆板子改电路。所以我的建议是BOOT0用一个跳线帽或者0欧电阻预留出来BOOT1也留个选择位。多两个元件换来的是调试灵活性这笔账很划算。另外去耦电容这块也是重灾区。STM32F103C8T6有多个VDD和VSS引脚每个电源引脚旁边都应该放一个100nF的陶瓷电容越靠近引脚越好。VBAT引脚如果不用电池也要接VDD并加去耦。这些细节在数据手册的电源部分写得清清楚楚但很多人画图的时候直接忽略了。2.2 电源方案怎么选LDO还是DC-DC最小系统板的输入电源通常是5VUSB或者外部适配器MCU需要3.3V。这里有两个选择LDO线性稳压和DC-DC开关稳压。LDO的优点是电路简单、输出纹波小、没有开关噪声缺点是效率低、发热大。如果输入5V输出3.3V压差1.7V假设电流100mA那LDO自身就要消耗0.17W的功率SOT-23封装的LDO会明显发热。但对于最小系统板这种几十到一百多毫安的负载LDO完全够用而且纹波小对ADC采样和晶振稳定性更友好。DC-DC效率高但需要电感、二极管、反馈电阻布局不好还会引入开关噪声干扰MCU的模拟部分。除非你的板子要带很多外设、电流需求大否则最小系统板用LDO是更稳妥的选择。我常用的方案是AMS1117-3.3或者RT9013。AMS1117便宜好买但静态电流偏大、压差要求高约1.1V输入5V时输出3.3V没问题。RT9013压差更低、静态电流更小适合电池供电场景。选哪个看你的实际需求但记住一点LDO的输入输出都要加电容输入侧建议10uF输出侧建议10uF加100nF这样能有效抑制纹波和瞬态响应。2.3 晶振电路8MHz主晶振和32.768kHz RTC晶振STM32F103C8T6的主时钟来源有几个选项内部HSI8MHz、外部HSE通常8MHz、内部LSI、外部LSE32.768kHz。最小系统板一般都会焊一个8MHz的外部晶振因为HSE的精度比HSI高得多而且用HSE配合PLL可以稳定跑到72MHz。晶振电路看起来简单就两个电容加一个晶体但坑特别多。负载电容的计算是关键CL (C1 * C2) / (C1 C2) Cstray其中Cstray是PCB走线的寄生电容一般取3到5pF。假设晶振的负载电容要求是20pF那C1和C2大概各取22pF到27pF。但实际选值还要看晶振手册不同厂家的晶振负载电容要求不一样。我踩过的坑是用了错误的负载电容导致晶振起振困难有时候能起振有时候不能特别在低温环境下更容易出问题。后来用示波器测晶振引脚发现波形幅度很小、频率偏移换了匹配的电容之后就稳定了。所以晶振电容不要随便抄别人的值一定要看自己用的晶振手册。另外晶振的布局也很讲究。晶振和负载电容要尽量靠近MCU的OSC引脚走线要短、要对称下方最好不要走其他信号线尤其是高频信号。晶振下方铺地可以但不要铺电源。有些设计还会在晶振旁边加一个1M欧的反馈电阻STM32内部其实已经有这个电阻了外部一般不需要再加。32.768kHz的RTC晶振是可选的如果你不用RTC功能可以不焊。但如果要焊同样要注意负载电容通常是6pF或12.5pF对应的电容值在10pF到22pF之间。RTC晶振的走线更要小心因为它频率低、驱动能力弱容易被干扰。2.4 复位电路阻容复位还是专用复位芯片STM32F103C8T6的NRST引脚是低电平复位内部有上拉电阻但为了可靠复位外部一般会加一个100nF电容到地再配一个10k欧的上拉电阻。这就是最经典的阻容复位电路。但阻容复位有个问题如果电源上升速度慢或者有抖动复位引脚的电平可能处于不确定状态导致MCU反复复位或者不复位。所以有些设计会用专用的复位芯片比如MAX809或者STM32内部的POR/PDR电路。实际上STM32F103内部已经有上电复位和掉电复位电路外部阻容复位主要是为了手动复位和增强抗干扰能力。我的做法是NRST引脚接一个100nF电容到地再并一个10k欧上拉到3.3V同时接一个复位按键。按键按下时NRST拉低松开后电容充电复位释放。这个电路简单可靠实测下来没问题。注意电容不要太大否则复位释放太慢影响启动时间也不要太小否则抗干扰能力差。100nF是个比较平衡的值。2.5 BOOT模式配置别小看这两个引脚BOOT0和BOOT1PB2决定了MCU上电后的启动模式。BOOT00时从主Flash启动这是正常运行的模式BOOT01、BOOT10时从系统存储器启动也就是Bootloader模式可以用串口下载程序BOOT01、BOOT11时从SRAM启动一般用于调试。很多最小系统板为了省事把BOOT0直接接地这样确实能正常运行但想用串口下载的时候就麻烦了。我的建议是BOOT0用一个2.54mm的排针加跳线帽或者用一个0欧电阻选择。BOOT1一般不用改直接接地就行因为从SRAM启动的场景很少。这里有个细节BOOT0引脚在复位期间的电平会被锁存所以跳线帽要在上电前就设置好。如果你在运行中改变BOOT0不会立即生效必须复位后才能进入对应的启动模式。3. 原理图设计细节与参数计算3.1 电源部分的完整设计电源部分从USB的5V或者外部5V输入开始。首先加一个自恢复保险丝或者肖特基二极管做防反接保护然后接LDO的输入端。LDO输入端加一个10uF的钽电容或者陶瓷电容输出端加10uF加100nF。这里有个计算LDO的功耗P (Vin - Vout) * Iout。假设Vin5VVout3.3VIout150mA那P 1.7 * 0.15 0.255W。SOT-23封装的LDO热阻大约250°C/W温升就是0.255 * 250 64°C。如果环境温度25°C结温就是89°C还在安全范围内。但如果电流再大就要考虑换封装或者加散热铜皮。去耦电容的布局每个VDD引脚旁边放一个100nFVBAT引脚也放一个100nF。另外在电源入口处放一个10uF的 bulk电容。这些电容要尽量靠近引脚走线要短而粗。我一般会在PCB上把100nF电容放在MCU的同一面紧贴引脚电源走线先经过电容再进引脚。3.2 晶振电路的参数确定以8MHz晶振为例假设晶振手册给出的负载电容CL20pFPCB寄生电容Cstray取4pF。那外部电容C1C22*(CL - Cstray) 2*(20-4) 32pF。但实际常用的值是22pF到33pF因为晶振的实际负载电容和手册值可能有偏差而且Cstray的估算也不精确。我的做法是先按计算值选电容焊好之后用频率计或者示波器测晶振频率如果偏差大就调整电容值。一般来说电容偏大频率会偏低电容偏小频率会偏高。对于8MHz晶振频率偏差在几十ppm以内都可以接受因为PLL会倍频到72MHz偏差也会被放大所以晶振精度很重要。晶振的走线OSC_IN和OSC_OUT两根线要尽量短、尽量对称最好包地处理。晶振下方不要走其他信号线尤其是SWD或者USB的差分线。如果板子空间允许晶振周围可以加一个接地屏蔽罩的焊盘但一般最小系统板不需要这么讲究。3.3 复位电路的参数选择NRST引脚的复位电路100nF电容到地10k欧上拉到3.3V。复位按键并联在电容两端按下时NRST拉低。复位时间常数τ R * C 10k * 100nF 1ms。复位释放后NRST电压从0上升到3.3V的63%需要1ms上升到90%需要2.3ms。STM32的复位阈值大约是2V左右所以复位释放时间大约在1ms到2ms之间。这个时间足够MCU完成上电初始化。如果电容取大了比如1uF那τ10ms复位释放要20多ms启动会变慢。如果电容取小了比如10nFτ0.1ms抗干扰能力就差容易误复位。所以100nF是个比较合适的值。3.4 SWD调试接口的接线SWD接口只需要两根线SWDIO和SWCLK再加上GND和3.3V。SWDIO对应PA13SWCLK对应PA14。这两个引脚在MCU内部有上拉外部一般不需要再加。但要注意PA13和PA14在复位后默认是SWD功能如果你在程序里把它们配置成普通GPIO那下次下载程序的时候就连不上了。所以调试接口的引脚要谨慎复用或者用SWD的复位引脚NRST配合下载器强制复位。SWD接口的布局尽量靠近MCU走线短而直不要和晶振或者电源走线平行。如果板子上有多个GND引脚SWD的GND要单独走一根线到MCU的GND不要和功率地混在一起。3.5 其他外围电路LED、按键、USB最小系统板一般会加一个电源指示灯和一个用户LED。电源指示灯接在3.3V和GND之间串一个1k欧电阻。用户LED接在某个GPIO上比如PC13串一个470欧到1k欧的电阻。按键可以加一个复位按键和一个用户按键。用户按键接在某个GPIO上另一端接地GPIO配置为上拉输入。注意按键要加消抖电容一般100nF就够了。USB接口如果只是供电那只需要VBUS和GND。如果要用来通信那D和D-要接PA12和PA11并且要加22欧的匹配电阻。USB的差分线要走90欧姆的差分阻抗走线要等长、平行、尽量短。4. PCB布局布线的实操要点4.1 布局原则先大后小先核心后外围PCB布局的第一步是把MCU放在板子中间或者偏一侧然后围绕MCU放置晶振、复位电路、去耦电容、LDO、接口。晶振要尽量靠近MCU的OSC引脚走线长度最好控制在10mm以内。去耦电容要放在MCU的同一面紧贴VDD引脚电源走线先经过电容再进引脚。LDO要放在电源入口附近输入输出电容紧贴LDO引脚。SWD接口放在板子边缘方便插下载器。USB接口也放在边缘方便插线。BOOT跳线放在容易操作的位置不要被其他元件挡住。4.2 电源走线宽度和过孔的计算电源走线的宽度要根据电流来算。1盎司铜厚的情况下1mm宽的走线大约能承载1A的电流温升10°C。但实际设计要留余量我一般用0.5mm到1mm的走线宽度。过孔的数量也要算一个0.3mm孔径的过孔大约能承载0.5A的电流。如果电源电流是200mA那一个过孔就够了。但为了降低阻抗我一般会放两个过孔。电源走线要尽量短而粗避免走细长线。如果板子有多个电源层那最好用平面分割但最小系统板一般是双层板所以电源走线要手动优化。4.3 晶振走线短、对称、包地晶振的走线是最讲究的。OSC_IN和OSC_OUT两根线要尽量短最好不超过10mm。两根线要对称长度差控制在1mm以内。走线下方不要走其他信号线尤其是高频信号。晶振周围可以包地但包地要完整不要有断点。包地的过孔要密集间距小于λ/20对于8MHz信号波长是37.5米λ/20是1.875米所以过孔间距只要小于1.8米就行实际上随便放几个过孔就够了。晶振的负载电容要放在晶振和MCU之间走线要短。电容的接地端要直接接到GND平面不要走长线。4.4 去耦电容的布局靠近引脚先电容后引脚去耦电容的作用是提供瞬态电流所以必须靠近MCU的电源引脚。我一般把100nF电容放在MCU的同一面紧贴引脚电源走线先经过电容再进引脚。电容的接地端要直接接到GND平面过孔要尽量靠近电容的焊盘。如果板子是双层板那GND走线要尽量宽最好铺地。多个去耦电容之间不要串联要并联。每个VDD引脚都要有独立的去耦电容不要共用。4.5 接地处理单点接地还是多点接地最小系统板的接地一般用多点接地也就是铺地。双层板的底层可以整层铺地顶层的空白区域也铺地然后通过过孔连接。但要注意模拟地和数字地要分开。STM32F103C8T6有VDDA和VSSA引脚这是模拟电源和模拟地。如果板子上有ADC或者DAC应用那VDDA要单独走线VSSA要单独接地最后在一点汇合。如果不用模拟功能VDDA可以接VDDVSSA可以接VSS。但为了保险我一般还是会把VDDA和VSSA单独处理加一个磁珠或者0欧电阻连接。4.6 丝印和标注方便调试和焊接丝印要清晰标注每个引脚的功能尤其是电源、地、SWD、BOOT、晶振这些关键引脚。元件位号要放在元件旁边不要被挡住。我一般会在板子上标注版本号、日期、设计者信息方便后续维护。接口的引脚定义也要标清楚比如SWD接口的1脚是3.3V、2脚是SWDIO、3脚是SWCLK、4脚是GND。5. 实操过程与核心环节实现5.1 从零开始画原理图的完整流程第一步新建工程选择STM32F103C8T6的符号。如果库里没有可以从官网下载或者自己画。自己画的时候要注意引脚编号和名称要和数据手册一致。第二步放置MCU然后依次放置电源电路、复位电路、晶振电路、BOOT电路、SWD接口、LED和按键。第三步连接网络。电源网络用VDD_3V3和GND晶振网络用OSC_IN和OSC_OUT复位网络用NRSTSWD网络用SWDIO和SWCLK。第四步检查连接。用ERC电气规则检查工具检查有没有未连接的引脚、电源冲突、短路等问题。第五步分配封装。每个元件都要指定正确的封装比如MCU用LQFP48电阻电容用0603或者0805晶振用HC-49S或者贴片晶振。第六步生成网表导入PCB。5.2 关键参数的实测与验证晶振频率的测量用示波器接在OSC_OUT引脚上探头要选10X档避免探头电容影响晶振。测到的频率应该在8MHz附近偏差在几十ppm以内。电源纹波的测量用示波器接在3.3V和GND之间探头要选AC耦合带宽限制到20MHz。测到的纹波应该在几十mV以内如果超过100mV就要检查去耦电容和LDO。复位时间的测量用示波器接在NRST引脚上按下复位按键观察NRST从低到高的上升时间。应该在1ms到2ms之间。SWD通信的验证用ST-Link或者J-Link连接SWD接口用STM32CubeProgrammer或者Keil MDK尝试连接。如果能读到芯片ID说明SWD通信正常。5.3 焊接与调试的注意事项焊接顺序先焊MCU再焊晶振、复位电路、LDO最后焊接口和按键。MCU的引脚比较密建议用热风枪或者细烙铁头加助焊剂避免连锡。焊接温度无铅焊锡的熔点大约217°C烙铁温度建议320°C到350°C热风枪温度建议300°C到350°C。温度太高会损坏元件温度太低会虚焊。调试步骤先不焊MCU只焊电源部分上电测3.3V是否正常。然后焊MCU测晶振是否起振。然后连SWD测能否下载程序。最后焊其他外围测功能是否正常。5.4 程序下载与运行验证用STM32CubeMX配置时钟HSE选8MHzPLL倍频到72MHzAHB、APB1、APB2的分频系数按默认设置。生成代码后在main函数里加一个LED闪烁的程序。编译下载用Keil MDK或者STM32CubeIDE编译用ST-Link下载。下载成功后复位MCU观察LED是否闪烁。如果LED不闪检查BOOT0是否接地、晶振是否起振、复位电路是否正常、电源是否稳定、SWD是否连接正确。6. 常见问题与排查技巧实录6.1 晶振不起振的排查思路晶振不起振是最常见的问题之一。排查步骤测晶振引脚电压正常情况下OSC_IN和OSC_OUT的电压应该在1V到2V之间接近VDD/2。如果电压是0V或者3.3V说明晶振没起振。检查负载电容电容值是否匹配晶振的负载电容要求。如果不确定可以试着换小一点的电容比如从22pF换到10pF。检查焊接晶振和电容是否虚焊引脚是否短路。检查PCB布局晶振走线是否太长是否靠近干扰源。换晶振有些晶振质量不好起振困难换一个品牌的试试。6.2 SWD连接失败的常见原因SWD连接失败的原因很多常见的有BOOT0没有接地MCU进入了Bootloader模式。SWDIO和SWCLK接反了。NRST没有接下载器无法复位MCU。MCU的SWD引脚被程序配置成了普通GPIO。电源不稳定MCU工作异常。下载器的驱动没有安装好。排查方法先用万用表测SWDIO和SWCLK的对地阻抗正常应该在几十k欧到几百k欧之间。如果阻抗很低说明有短路。然后测NRST电压正常应该是3.3V。最后用下载器的复位模式选择Connect under reset。6.3 电源纹波过大的解决方法电源纹波过大可能导致MCU工作不稳定、ADC采样不准、晶振频率偏移。解决方法增加去耦电容每个VDD引脚加100nF电源入口加10uF。换LDO有些LDO的纹波抑制比不好换一个PSRR高的LDO。优化布局去耦电容靠近引脚电源走线短而粗。加LC滤波在电源入口加一个磁珠和电容组成的LC滤波器。6.4 复位电路误触发的处理复位电路误触发表现为MCU频繁复位或者上电不运行。原因可能是复位电容太小抗干扰能力差。复位走线太长引入了干扰。复位按键没有消抖电容。电源上升速度慢复位释放时间不够。解决方法增大复位电容到100nF缩短复位走线加消抖电容检查电源上升时间。6.5 常见问题速查表问题现象可能原因排查方法解决方案晶振不起振负载电容不匹配测晶振引脚电压调整电容值SWD连接失败BOOT0未接地测BOOT0电压接地或跳线电源纹波大去耦电容不足示波器测纹波增加去耦电容频繁复位复位电容太小测NRST波形增大电容程序下载后不运行BOOT模式错误测BOOT0/BOOT1设置正确模式LED不亮GPIO配置错误测GPIO电压检查程序发热严重LDO功耗过大测LDO电流换LDO或降低电流6.6 独家避坑技巧第一个坑晶振的负载电容不要照抄别人的值。我见过有人用22pF的电容配6pF负载电容的晶振结果晶振频率偏了100多ppmPLL倍频后偏差更大串口通信都出问题。一定要看自己用的晶振手册。第二个坑BOOT0不要直接接地。留一个跳线帽调试的时候方便。我因为BOOT0接地想用串口下载的时候拆了好几次板子。第三个坑去耦电容不要省。有人觉得100nF电容太多只放一个10uF的结果MCU工作不稳定。每个VDD引脚都要有100nF这是底线。第四个坑SWD接口的GND要单独走线。如果和功率地混在一起下载的时候容易受干扰连接不稳定。第五个坑LDO的输入输出电容不要省。有人只放输出电容不放输入电容结果LDO自激振荡输出电压不稳。第六个坑晶振下方不要走线。我见过有人在晶振下方走了一根PWM信号线结果晶振频率被调制MCU跑飞。第七个坑复位按键要加消抖电容。不加的话按一次复位可能触发多次复位MCU启动异常。第八个坑PCB的丝印要标清楚。调试的时候找不到引脚浪费时间。7. 从设计到量产的延伸思考7.1 国产替代料的选型考量STM32F103C8T6的国产替代料不少比如GD32F103C8T6、APM32F103C8T6、CH32F103C8T6等。这些料在引脚和寄存器层面基本兼容但也有一些差异。GD32F103C8T6的主频可以跑到108MHzFlash和SRAM更大但功耗也更高。APM32F103C8T6的功耗更低适合电池供电。CH32F103C8T6的价格更便宜但生态和资料相对少一些。选替代料的时候要注意晶振的负载电容要求可能不同复位电路的门限电压可能不同SWD的时序可能不同。最好先买样品测试确认兼容性后再批量使用。7.2 PCB打样和SMT的注意事项PCB打样的时候要注意板厚选1.6mm铜厚选1盎司表面处理选沉金或者喷锡。沉金的可焊性更好但价格贵一些。喷锡便宜但平整度差一些。SMT的时候要注意元件的封装要和PCB的焊盘匹配钢网的开口要合适回流焊的温度曲线要调好。MCU的引脚比较密容易连锡建议用免清洗助焊剂。7.3 后续功能扩展的方向最小系统板跑通之后可以扩展很多功能加一个OLED显示屏加一个DHT11温湿度传感器加一个WS2812B灯带加一个TB6612电机驱动加一个编码器接口加一个CAN收发器加一个USB转串口芯片。扩展的时候要注意电源的电流要够GPIO的驱动能力要够通信接口的电平要匹配。比如WS2812B需要5V供电但数据线是3.3V电平可能需要电平转换。7.4 加密和固件保护STM32F103C8T6支持读保护RDP和写保护WRP。读保护可以防止别人通过SWD读出Flash里的程序写保护可以防止程序被篡改。设置读保护的方法用STM32CubeProgrammer或者ST-Link Utility在Option Bytes里设置RDP等级。等级1是读保护等级2是永久读保护不可逆。设置之前要确认程序已经调试完毕因为设置读保护后SWD就读不出Flash了。固件保护还可以用唯一ID加密每个STM32F103C8T6都有一个96位的唯一ID可以用这个ID生成密钥程序运行时校验密钥防止固件被复制到其他芯片上运行。7.5 低功耗设计的考虑如果最小系统板要用在电池供电的场景低功耗设计就很重要。STM32F103C8T6支持睡眠、停止、待机三种低功耗模式。待机模式的电流可以低到2uA左右。低功耗设计的要点不用的外设要关闭时钟不用的GPIO要配置成模拟输入或者下拉LDO要选静态电流小的LED要选低功耗的或者去掉。晶振也可以选择低功耗的比如32.768kHz的RTC晶振在待机模式下可以保持运行主晶振可以关闭。8. 个人实操体会与建议画这块板子前后我打了五版前两版都有各种小问题第三版开始稳定。最大的体会是最小系统板看着简单但每一个元件、每一根走线都有它的道理不能随便省。晶振的负载电容一定要看手册不要抄别人的值。BOOT0一定要留跳线不要直接接地。去耦电容一定要每个VDD引脚都放不要省。SWD接口的GND一定要单独走线不要和功率地混在一起。还有一点PCB布局的时候先放MCU再放晶振和去耦电容再放LDO和接口。晶振和去耦电容要尽量靠近MCULDO要靠近电源入口。走线的时候电源线要粗信号线要短晶振线要对称。最后分享一个小技巧板子焊好之后先不要急着上电用万用表测一下3.3V和GND之间的阻抗正常应该在几百欧到几千欧之间。如果阻抗很低说明有短路要先排查再上电。这个习惯帮我避免了好几次烧芯片的事故。这个板子后续还可以扩展成一个完整的开发平台加显示屏、传感器、通信模块做成一个通用的嵌入式开发板。但那是下一步的事了先把最小系统跑稳后面的事情自然水到渠成。