简介:面向STM32F103C8T6智能小车开发者的一份核心板硬件工程设计资源。整套图纸用Altium Designer绘制,覆盖原理图、PCB图与元件库,不仅适用于智能小车,也可移植到其他STM32F103C8T6核心板场景,适合嵌入式入门者学习画板,也适合创客直接打样制作。压缩包内含61个文件,大小15.09MB,主要包括AD工程源文件(SchDoc、PcbDoc、SchLib、PcbLib)、DRC检查报告、网络表、预审PDF以及多版本备份,便于查看设计细节与追踪演进。设计已由作者实际打样并验证通过,硬件可靠度较高;附带的设计规则检查文件还可以辅助排查布线隐患。目前已有1065人学习下载,若还需配套驱动板,可搜索“STM32智能小车驱动板原理图和PCB图”,组合构成完整小车方案。
1. 拿到 STM32 智能小车核心板压缩包,先想清楚要干什么
如果你在某个资料站或学长网盘里看到“STM32 智能小车核心板原理图和 PCB 图.rar”这个文件名,大概率不是第一次接触单片机。这个东西解压出来就是一份 Altium Designer 或嘉立创的工程——原理图告诉你芯片引脚怎么连,PCB 图告诉你怎么布板,而“核心板”这三个字意味着它不包含电机驱动和传感器,只是最小系统加上必要的接口排针。你的任务不是欣赏电路,而是要把这块板子读懂、改对、或者直接制板回来自己焊,然后配上一块电机驱动板和几个红外传感器,拼出一台能巡线、能避障的小车。
这篇博文会从原理图的最小系统开始讲起,再落到 PCB 布局怎么排,最后给出把板子跑起来的固件骨架和排错路径。全程不依赖某个具体开源项目的源码,只按一线工程师拿到这类资料时“先看电源、再看时钟、然后接口、最后写驱动”的顺序来拆解,保证你解压后不迷路。
2. STM32 最小系统原理图的五个必读模块
2.1 电源树先于一切:从 USB 或 DC 口扒起
打开原理图先别盯着 STM32 看,第一件事是顺着电源入口理出整棵电源树。最常见的设计是 USB 5V 或 7.4V 锂电池经过一个二极管防反接,再进入稳压芯片。核心板上通常用 AMS1117-3.3,有些新设计会用 ME6211 这类低压差 LDO,压差低到 0.2V,适合电池电压偏低时仍能稳住 3.3V 输出。
电源部分要确认三件事:
- 输入电压范围是多少,是否在你的小车电源选择范围内;
- 3.3V 输出电容用的是不是 10uF + 100nF 的组合,LDO 的 ESR 要求是否满足;
- 有没有电源指示灯和防反接二极管,没有的话焊接时容易烧片子。
# 电源部分的元件位号习惯(仅作参考,以实际原理图为准) U2 AMS1117-3.3 Vin=5V, Vout=3.3V, Iout 最大 1A C5 10uF/0805 输入侧滤波电容 C7 100nF/0603 输出侧高频去耦 D1 SS14 防反接肖特基二极管注意 AMS1117 的压差在 800mA 时大约 1.2V,这意味着输入电压至少要 4.5V 才能稳定输出 3.3V。如果你用的是两节 18650 串联(约 7.4V),那就没问题;如果打算用 USB 直接供电,5V 输入压差只剩 1.7V,还行,但低电量时会掉到稳压范围之外。阅读原理图时,把电源路径的电容值顺带记下来,后面做 PCB 检查时要用到。
2.2 时钟电路与复位电路:最容易照抄却抄错的两块
STM32 核心板的时钟源有两种。一种是用 8MHz 无源晶振配合两个 20pF 负载电容,接到 OSC_IN/OSC_OUT;另一种是直接从 STM32 内部 HSI 启动,省掉外部晶振。你在原理图上看到 Y1 和 C9、C10 就是前者,Y1 丝印旁边标着 8.000MHz,两个电容取值通常在 10~22pF 之间,具体要查晶振的 CL(负载电容)规格。
晶振电路常见的错误是:电容接地走线太长、晶振底下铺铜、两个负载电容没对称放置。后面 PCB 布局时会展开说,原理图阶段只确认一点——是否有并联一个 1MΩ 反馈电阻在晶振两端。有些低成本设计会省略它,实际也能起振,但起振时间和稳定性会差一些。
复位电路更直接:NRST 引脚接一个 100nF 电容到地,再通过 10K 电阻上拉到 VCC。这个 RC 时间常数大约是 1ms,足够让 STM32 在上电时完成内部复位。有个判断技巧:如果你看到 NRST 直接接 VCC 没有任何电阻电容,那这块核心板省略了外部复位电路,靠 STM32 内部 POR 工作,也能跑,但调试器连接时更容易出现握手失败。
2.3 BOOT 引脚与下载电路:决定你能不能烧进程序
BOOT0 和 BOOT1 的接法只在原理图阶段排错最直观。BOOT1 一般直接拉地,BOOT0 则通过一个 10K 电阻下拉到地,同时引出焊盘或短接帽。这个设计允许你把 BOOT0 上拉到 3.3V 进入 ISP 下载模式,而默认下拉则从 Flash 启动。如果你发现 BOOT0 悬空没接电阻——悬空的 CMOS 输入引脚会随机读高低电平,下载后程序偶尔跑飞,就是这里埋的雷。
下载调试接口方面,2025 年的核心板基本标配 SWD,四根线:SWDIO、SWCLK、VCC、GND,有些还会带一个 NRST。原理图上标识通常是 P1 或 J1,旁边注明“SWD”字样。个别老核心板还会拉出一组串口 TX/RX 来做串口下载,如果你用的是 ST-Link 或者 DAP-Link,SWD 足够了,串口下载口可以空着不焊。
# SWD 接口顺序,常规接法 Pin1 VCC(3.3V) Pin2 SWDIO Pin3 SWCLK Pin4 GND注意 ST-Link 的 SWD 线序和这块板子的丝印未必一致,接线前对照原理图确认,别盲目按颜色插。SWDIO 和 SWCLK 不要接反,接反后调试器报错“No target connected”,很多人误以为芯片坏了,其实是线序问题。
2.4 最小系统通用性判断:这套设计能不能跑 RTOS 和 FSMC
看核心板原理图的最高层次判断,是确认它是“最小系统板”还是“带外设的增强板”。以 STM32F103C8T6 为例,最小系统板会引出全部 20 个 GPIO 到两排 2.54mm 排针,外设只保留板载 LED(PC13)、按键、USB 从机口。这种设计在智能小车场景下有个好处——电机驱动和传感器接口全部外接,核心板布线和底层驱动可以独立调好,再拼到小车底盘上。
而如果你看的是 STM32F103ZET6 的核心板,通常会有 FSMC 液晶屏接口、SDIO、16 位排针等。对智能小车来说,ZET6 的核心板有点浪费,C8T6 就能干完循迹避障的全部活,而且功耗更低。原理图阶段判断标准就一条:GPIO 引出数量是否满足小车外设需求(电机 PWM 至少 4 路、编码器至少 4 路、红外循迹至少 2 路、超声波 2 路、OLED 备用 4 路,合计约 16 个引脚)。C8T6 有 37 个 GPIO,除去晶振和下载占用的,仍有余量。
2.5 电机驱动与传感器接口:核心板如何外接动力系统
核心板本身不带电机驱动,这是设计边界。原理图上你看到的电机相关引脚,其实是引出的 PWM 输出和电源接口,比如标着 TIM1_CH1、TIM2_CH2 的排针孔。智能小车用 H 桥驱动板(如 TB6612FNG)时,接线方式是:
| STM32 引脚 | 驱动板信号 | 说明 |
|---|---|---|
| PA0 | PWMA | 左轮占空比信号 |
| PA1 | AIN1 | 左轮方向控制 |
| PA2 | AIN2 | 左轮方向控制 |
| PA6 | PWMB | 右轮占空比信号 |
| PA7 | BIN1 | 右轮方向控制 |
| PB0 | BIN2 | 右轮方向控制 |
注意 PWM 信号必须来自定时器的通道引脚,普通 GPIO 只能输出高低电平,不能输出可调占空比的方波。F103 的 TIM2、TIM3、TIM4 各有 4 个通道,足够两路电机 PWM。原理图里只需要确认这些引脚被引出到排针,如果某个脚被板载外设占用了,改固件时要重新映射定时器通道。
3. PCB 布局与制板:原理图正确不等于板子能车
3.1 布局顺序:从核心到外圈,电源和 MCU 中心化
PCB 布局的思路和原理图阅读不一样,你不能照着原理图信号流从左到右铺,而要把板子当成一个物理系统来安排。核心板的布局顺序一般是:MCU 居中偏上,晶振紧贴 MCU 引脚,去耦电容在 MCU 电源脚正对面,排针分布在两侧,电源 LDO 在输入接口附近,指示灯远离晶振。
布局时用位号图做一致性检查,确保 PCB 上的 C5 就是原理图里的 C5,D1 就是那个防反接二极管。这个动作是 Gerber 文件发给板厂前必做的。如果你用的是嘉立创 EDA,它有“位号检查”功能,能自动比对;如果你在用 Altium,就得手动交叉查,重点查电阻电容的容值丝印和焊盘编号。
电源通路要短而粗。从输入端子到 LDO 再到 MCU 的 VCC 引脚,走线宽度至少 0.5mm 以上,电机驱动电流不走核心板(电机是外接的),但核心板上的电源总线仍然要为舵机等大电流外设预留余量。电源线先到 MCU 再分支去其他外设的星型连接方式,比链式连接更好,能减少负载变化对 MCU 供电的干扰。
3.2 晶振与去耦电容的位置优先级最高
晶振布局是整个核心板 PCB 质量的分水岭。8MHz 晶振要放在 MCU 的 OSC_IN/OSC_OUT 引脚之间,不要超过 5mm 走线距离;两个负载电容分别从晶振两端引出,在同一侧接地,地孔直接打到主地层,不要共用过孔穿过信号层。晶振区域下方不得走任何数字信号线,尤其是 USART 和定时器的 PWM 线,这些信号的谐波会干扰晶振起振。
# 晶振布局的几何约束,AD 里按 MM 单位设置 Y1 中心距 MCU 边缘 3~5mm C9、C10 分别距 Y1 两端小于 2mm Y1 下方禁止布线区域 0.5mm 半径 两个地过孔间距不超过 3mm如果晶振电容的实际封装是 0402 或 0603,设计时要留意焊盘到晶振引脚焊盘的连线不能形成锐角,建议用 45 度角走线。去耦电容方面,每个电源引脚对应的 100nF 电容必须放在引脚背面的地平面旁,过孔直接连接电容的地焊盘和主地层,不要四处拉长线。
3.3 排针接口与信号线的接线顺序技巧
核心板两侧排针是它的对外骨架,排针的顺序定义直接影响后面接线是否顺手。优秀的设计会把电源脚集中在一端——最上面 3 个脚是 VCC、GND、3V3,下面才是 GPIO——这样外接电机驱动板时,电源跳线不会横跨整块板子。信号线走线尽量在外层,不要内外层反复换层。STM32F103 的 GPIO 自带施密特触发器和 ESD 保护,但输入口走线过长且贴近 PWM 线时,会产生串扰,引起循迹信号误判。
排针封装选择上,直插排针的机械强度优于排母,但排母方便插拔。核心板如果有固定孔,四个角各一个 2.0mm 通孔用于锁铜柱,这样装在小车底盘上不会因为振动导致接触不良。外接插线端子如果是 XH2.54 或者 PH2.0,注意丝印标注正负极,反转会直接烧毁超声波的电源管理芯片。
对比参数和适用场景,核心板布局里常见的取舍如下:
| 设计选择 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 双层板 | 成本低、制板快 | 地平面不完整、EMI 稍差 | 学习板、课程设计 |
| 四层板 | 完整地层、信号质量好 | 成本高约一倍 | 竞赛小车、量产原型 |
| 贴片排针 | 不占空间、更小巧 | 机械强度弱 | 固定外设的小车 |
| 直插排针 | 耐用、拔插方便 | 板子面积更大 | 换模块频繁的开发阶段 |
3.4 板厂打样的参数设置与常见加工坑
PCB 画好后导出的 Gerber 文件,发板厂时有三项参数必须确认:板厚(1.6mm 标准)、铜厚(1oz 常规,大电流回路可加粗到 2oz)、表面处理(有铅喷锡最便宜,无铅价格略高,对核心板性能没有实质影响)。还有一个容易忽略的是最小线宽/间距,嘉立创、捷配等常规板厂默认为 6mil 线宽 6mil 间距,如果你画的时候用了 5mil 线间距,干到板厂那边会直接给你报制造问题,或者更糟的是被自动改宽,导致布局改变。
值得专门说到的一个坑:引脚间距 0.65mm 的 LQFP48 封装,焊盘中心距才 0.5mm,过孔只能放在封装外侧,放内侧会造成焊盘短路。打印 1:1 图纸或三维预览确认一下排针和电容没有压到芯片顶部,这个动作能省一次打板费。还有位号图的问题,如果原理图里有两张图纸页且页码重复为 1,导出网表时元件会错乱,EDA 工具在 DRD 前必须消除页码重复。
4. 固件骨架与下载验证:把板子变成能跑的小车
4.1 从核心板到最小电机控制的代码路径
核心板焊好后,第一个验证固件不需要复杂逻辑,只需让两个 LED 闪烁、串口输出“OK”,就走完了从芯片上电到外设工作的完整链路。用 STM32CubeMX 生成工程时,晶振源要选 Crystal/Ceramic Resonator,对应 8MHz 外部晶振;如果选错为内部 RC,系统时钟会从 64MHz 掉到 8MHz,PWM 频率会同步偏差。
# CubeMX 关键配置项 RCC: HSE = Crystal/Ceramic Resonator SYS: Debug = Serial Wire USART1: Asynchronous, 115200-8-N-1 GPIO: PC13 = Output Push Pull, Label = LED Clock: HSE -> PLL x9 -> SYSCLK 72MHz生成代码后打开 main.c,在while(1)里加一句HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); HAL_Delay(500);,然后在串口助手看有没有周期性的数据输出。注意 CubeMX 生成的函数HAL_Delay()依赖 SysTick 中断,如果你在代码里关了中断优先级设置,延时就会失效。
4.2 TIM 定时器产生电机 PWM:频率选择与占空比设置
真正驱动电机时,PWM 频率的选择很讲究,不能想当然。直流减速电机的调速频率在 10kHz~20kHz 之间效果最好,低于 5kHz 会听到明显的啸叫声,高于 20kHz 电机的电感感抗增大,电流反而上不去。我用 F103 驱动 TB6612,PWMA 设定为 10kHz,占空比从 0 到 999(以 1000 为满占空比基准)线性调。
// TIM2 PWM 初始化核心参数 htim2.Instance = TIM2; htim2.Init.Prescaler = 72 - 1; // 72MHz / 72 = 1MHz 计数频率 htim2.Init.Period = 100 - 1; // 1MHz / 100 = 10kHz PWM htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; // 通道 1 配置,PA0 输出 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 50; // 初始占空比 50% sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);参数解释:Prescaler 为 71 是因为定时器时钟来自 APB1 的 72MHz(在标准时基配置下),分频后得到 1MHz 计数时钟;Period 为 99,所以 PWM 周期是 100 个计数,即 10kHz;Pulse 设为 50 时占空比为 50/100 = 50%。改__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty)可以动态调速,duty 范围 0~99。
方向控制就简单了,AIN1 和 AIN2 两个 GPIO 一个给高一个给低,电机正转;反过来就是反转。程序里封装一个motor_left(int speed)函数,speed 正数前进负数后退,内部判断正负后修改 GPIO 和占空比。
4.3 使用 ST-Link 连接调试器的连接顺序和故障定位
连接调试器时按 ST-Link、杜邦线、核心板 SWD口 的顺序操作,优先接入 GND,再接 SWCLK、SWDIO,最后接 VCC(如果 ST-Link 有输出能力)。上电后打开 Keil 或 STM32CubeIDE,点下 Download 按钮前,先点一下 Settings 看 SWD 设备是否被识别,设备列表里出现 ARM CoreSight SW-DP 就是一个好信号。
常见的五种故障,按出现频率排序:
| 故障现象 | 排查点 | 解决手段 |
|---|---|---|
| No target connected | 接线是否反了 | 交换 SWDIO 和 SWCLK |
| 下载成功但程序不跑 | BOOT0 被拉高 | 确认 BOOT0 跳线在低电平 |
| 运行时 LED 微弱 | 供电不足 3.3V | 测量 LDO 输出电压 |
| 上电后芯片发热 | 电源反接或 3.3V 短路 | 用万用表蜂鸣档测 VCC 对 GND |
| 串口输出乱码 | 波特率不匹配 | 确认 CubeMX 和串口助手都是 115200 |
SWD 连接失败时要区分是板子的问题还是调试器的问题:拿 ST-Link 的 3.3V 和 GND 去测量核心板的输入电源,如果电压正常,再查 SWDIO 和 SWCLK 是否有短路到地的迹象。如果 ST-Link 连过其他板子没问题,那问题基本出在核心板这侧。
4.4 核心板配合电机驱动的整车上电时序
整车上电时,如果不注意时序,第一下就可能烧驱动芯片。正确流程:先让驱动板电源上电(电机电源单独接电池),延迟 100ms,再让 STM32 核心板上电。这是因为 TB6612 这类电机驱动在供电稳定前,逻辑输入高阻态可能让 AIN1 和 AIN2 同时为高,造成直通短路。
如果你把核心板和驱动板共用同一个电源开关(很多小车底盘确实这么做),可在核心板代码里加一个上电保护:初始化时先把 AIN1、AIN2 和 PWMA 全部拉低,延时 50ms 后再置为有效状态。这样即便驱动先上电,电机也不会立刻转动。
// 上电电机保护代码片段 HAL_GPIO_WritePin(AIN1_GPIO_Port, AIN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(AIN2_GPIO_Port, AIN2_Pin, GPIO_PIN_RESET); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 0); HAL_Delay(50); // 之后再进入主循环设置实际占空比现象说明:如果你上电瞬间小车猛冲一下,说明这段保护代码没生效,检查 GPIO 是否初始化在正确状态。还有一种情况是 PWM 启动函数HAL_TIM_PWM_Start()里占空比还没设置就被调用了,通道在默认 Pulse 值下输出高电平——这也会造成猛冲,务必先 SET_COMPARE 再 Start。
5. 用串口示波器验证控制环路的三个进阶步骤
5.1 把 PWM 波形拉到虚拟示波器:引脚复用观察技巧
当小车跑起来但不听话时,你需要能看到 PWM 波形才能知道是驱动板的问题还是代码的问题。如果没有实体示波器,用 ST-Link 虚拟示波器不够现实,但可以用串口加一个 GPIO 翻转来近似看控制周期。做法是:在定时器更新中断里翻转一个空闲 GPIO,然后在 main 函数里把串口数据按时间戳打印,就能在串口绘图软件(比如匿名的地面站或者简单的 SerialPlot)里看到控制量随时间的变化。
这个方法不直接看 PWM,而是看“控制周期是否卡住”。如果 GPIO 翻转时间间隔不均匀,说明中断被阻塞了,比如在中断里调用了HAL_Delay()或者长串口发送。核心板调试时,我习惯留一个空闲 GPIO 作为心跳引脚,既方便调试器逻辑分析仪测量,也可以在死循环排查时快速定位哪段代码卡住。
5.2 读取编码器数据:定时器编码器模式的参数设置参考
智能小车有了核心板之后,理论上应加装霍尔编码器电机,才能测速和闭环。F103 的定时器编码器模式把两个输入通道配置为 A/B 相正交信号,计数器按编码器旋转方向增减。CubeMX 里把 TIM2 的两个通道设为 Encoder Mode,不需要手动初始化 GPIO 复用,硬件自动捕获。
// 编码器模式初始化关键参数 htim2.Init.Prescaler = 0; htim2.Init.Period = 65535; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; // 编码器模式忽略此字段 sConfigIC.Polarity = TIM_ICPOLARITY_RISING; sConfigIC.Filter = 10; // 数字滤波,消除机械抖动 HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); int16_t encoder_value = (int16_t)__HAL_TIM_GET_COUNTER(&htim2);编码器计数范围是 16 位有符号数,正转增反转减,(int16_t)转换不能丢。读取间隔建议固定为 10ms 或 20ms,差值除以时间就是转速。如果你的电机编码器只有单相输出(没有正交 A/B),F103 的编码器模式用不了,得接外部中断配合定时器计数,精度会低一些。
5.3 开环转闭环:PID 参数由粗到细的调节顺序
核心板调试里最有质变的一步,是从“给一个占空比让它走”变成“读编码器让它稳在一固定速度上”。PID 参数的粗调遵循一个固定流程:先只调 P,让它能接近目标但有静差;再加 I 消掉静差;最后加 D 抑制超调。如果初始速度波动超过目标值的 30%,说明 P 太小;如果电机一直抖动,则是 P 太大或 D 太敏感。
// 位置式 PID 的简化实现,只用于核心板逻辑验证 float pid_result = Kp * error + Ki * integral + Kd * (error - last_error); // 限制输出范围 if (pid_result > 990) pid_result = 990; if (pid_result < -990) pid_result = -990;调节先从小车悬空状态开始,轮子离地,看速度响应是否能把编码器读数稳定在目标值附近。稳定后放到地上试跑,如果地上跑的和悬空的表现差异很大,优先检查电池电压是否在核心板稳压范围之外,或者电机驱动板的电流限流是否触发。闭环控制的采样时间固定在 20ms,避免用不固定的线程延时,不然 PID 输出会和实际转速不同步。
5.4 位号图与实物对照的最终验证清单
最后回到开头那份“原理图和 PCB 图.rar”,在所有调试完成后做一次完整对照。把 PCB 实物和位号图逐点对一遍,重点检查排针丝印上的编号与原理图网络标号一致:VCC 排针量一下和 LDO 输出的 3.3V 是否导通;GND 对地是否零欧姆;每个排针上的信号用万用表蜂鸣档从 MCU 的对应引脚位置反测回去。
值得养成的习惯是:在小车项目稳定运行后,把这份对照表导出为文本格式存到和压缩包同一目录,后续改板子或者换芯片型号时,按表核对电源、时钟、BOOT、排针四块,能省去从头翻原理图的时间。如果你搭配的是 STM32F405 类的新板子,原理图结构几乎相同,只是电源电压更低、去耦电容数量更多,把 C8T6 的调试经验搬过去,最多两天就能上手。
本文还有配套的精品资源,点击获取