
STM32F103C8T6这颗芯片玩嵌入式的应该都不陌生。作为Cortex-M3内核的性价比之王它几乎出现在每一个电子爱好者的入门清单里。而循迹避障小车恰好是能把这颗芯片的外设、中断、PWM、ADC这些资源全部调动起来的经典项目。网上关于这个小车的教程多如牛毛但很多都是片段式的要么只讲代码要么只讲接线真正从头到尾把硬件选型、组装、调试讲透的并不多。我这篇先聚焦整个制作过程的前三块项目规划与器件选型、电源与驱动核心、底盘组装与传感器安装。如果你正准备动手做一台属于自己的小车或者已经在做但卡在某个环节这篇内容应该能帮你省下不少弯路。1. 项目规划与器件选型解析1.1 为什么选STM32F103C8T6而不是Arduino很多新手一上来就问用Arduino Uno做循迹避障不是更简单吗确实Arduino有现成的库几行代码就能让电机转起来但这里有个很现实的问题Arduino的AVR单片机主频只有16MHzFlash只有32KB当你要同时处理两个循迹传感器的信号、一路超声波避障的脉冲计时、四路PWM输出还要跑PID调速算法时资源会非常紧张。而STM32F103C8T6虽然是入门级主频72MHzFlash 64KBSRAM 20KB性能几乎是Arduino的四倍价格却差不多。更重要的是STM32的TIM定时器可以同时输出多路不同频率的PWM配合DMA甚至可以不占CPU这对以后扩展功能非常友好。另外从学习价值来看ARM Cortex-M3架构是目前工业控制领域的主流学会了STM32的寄存器操作和HAL库开发后续不管是做物联网终端、无人机飞控还是移植FreeRTOS技能都是通用的。我见过不少用Arduino做小车的人做完就只会调库让他换个传感器就懵了。用STM32做虽然前期会多花点时间在环境配置和底层理解上但一次搞明白后面所有嵌入式项目都会顺利很多。1.2 核心器件清单与选型理由做循迹避障小车器件清单看起来简单但每一项都有讲究。我直接列出我这次用的配置并解释为什么这么选器件型号/规格选型理由主控板STM32F103C8T6最小系统板性价比高引脚全引出带8MHz晶振和USB转串口电机驱动L298N模块经典双H桥驱动能力强支持两路直流电机新手友好电机带减速箱的TT电机1:48扭矩够大转速适中适合小车爬坡和调速轮胎65mm橡胶轮编码器可选橡胶轮抓地力好编码器为后续测速做预留循迹传感器TCRT5000红外循迹模块 x2模拟量输出可调灵敏度检测黑白线效果好避障传感器HC-SR04超声波模块测距范围2cm-400cm精度3mm避障足够用电池18650锂电池 x2或4节5号镍氢电压7.4V/6V容量大续航时间长底盘亚克力3-4mm双层板便宜、易钻孔、绝缘比金属底盘轻电源模块AMS1117-3.3或MP1584降压模块给STM32提供稳定的3.3V或5V蜂鸣器/指示灯有源蜂鸣器LED若干调试辅助状态提示没屏幕时的好帮手这里特别注意电机的选择。TT电机常见的有1:48和1:120减速比之分1:48的意思是电机转子转48圈输出轴转1圈转速大约200rpm。这个速度配合65mm直径的轮子算下来小车速度大约0.7m/s对于室内循迹来说既不会太快失控也不会慢得像蜗牛。你要是选1:120的扭矩更大但速度只有80rpm左右跑起来就很着急了。至于要不要带编码器版本如果预算允许尽量带后续做速度闭环PID会非常有用哪怕这次用不上也不至于后面想加得重新拆底盘。1.3 功能规划与引脚分配预案拿到板子和器件后别急着接线先在纸上把功能模块划分好再分配GPIO引脚这是工程思维的第一步。我这次小车的功能需求有双电机差速转向、双路循迹检测、超声波避障、状态指示。基于这个需求我做了如下引脚预分配// 引脚分配预案后续代码实现时按此接线 // 电机驱动 L298N #define MOTOR_IN1 GPIO_PIN_8 // PA8 - 左电机正转 #define MOTOR_IN2 GPIO_PIN_9 // PA9 - 左电机反转 #define MOTOR_IN3 GPIO_PIN_10 // PA10 - 右电机正转 #define MOTOR_IN4 GPIO_PIN_11 // PA11 - 右电机反转 #define PWM_LEFT GPIO_PIN_0 // PA0 - TIM2_CH1 左电机PWM #define PWM_RIGHT GPIO_PIN_1 // PA1 - TIM2_CH2 右电机PWM // 循迹传感器数字量输出接GPIO #define TRACK_LEFT GPIO_PIN_0 // PB0 - 左循迹传感器 #define TRACK_RIGHT GPIO_PIN_1 // PB1 - 右循迹传感器 // 超声波模块 #define ULTRASONIC_TRIG GPIO_PIN_3 // PB3 - 触发信号 #define ULTRASONIC_ECHO GPIO_PIN_4 // PB4 - 回波信号 // 状态指示 #define LED_STATUS GPIO_PIN_5 // PB5 - LED指示灯 #define BUZZER_PIN GPIO_PIN_6 // PB6 - 蜂鸣器引脚分配的原则有三条一是PWM功能必须挂在具有定时器输出通道的引脚上比如PA0和PA1恰好对应TIM2的CH1和CH2二是超声波模块的ECHO引脚必须选择能接收外部中断的引脚且最好独立于PWM通道三是把指示灯和蜂鸣器这类调试辅助器件放在宽裕的GPIO上方便飞线连接。这个预案想明白后后面焊接和写代码就不会手忙脚乱。2. 电源与驱动核心构建2.1 电源树设计与电压逻辑电源是整个小车的命脉很多小车跑不起来或者跑着跑着复位十有八九是电源问题。我们先理清楚这个系统的电压需求电机驱动模块需要6-12V供电STM32最小系统板需要3.3V循迹模块和超声波模块需要5V。所以完整的电源分配是电池输出到L298N的12V输入端子L298N板载78M05稳压输出5V一路给传感器供电另一路接到LM1117-3.3模块降压到3.3V给STM32。有一个很多人忽略的坑L298N板上那个5V输出是从电机电源直接线性稳压来的如果你用两节18650串联7.4V78M05压差有2.4V输出电流又不可能太大稳压片会很烫。所以传感器模块这么多建议L298N的5V只给传感器供电STM32单独用一块MP1584降压模块接到电池这样两条线互不干扰稳定得多。实测下来这种方案哪怕电机堵转导致电压跌落STM32也不会复位。关于电池我强烈建议用两节18650锂电池串联标称7.4V。为什么不用四节5号镍氢镍氢单节1.2V四节正好4.8V接近5V虽然直接供电方便但电流输出能力有限急加速时压降大。而18650动辄20A放电能力给TT电机这种瞬间堵转电流2-3A的负载完全无压力。当然如果你手上只有5号电池架那就用4节配合L298N的5V输出接STM32的5V引脚靠板载稳压到3.3V也行续航差一些但能跑。2.2 L298N电机驱动的接线与逻辑真相L298N这块板子几乎是新手入门的标配驱动主要因为它便宜、皮实、接线简单。它内部是两个H桥每个H桥有四个功率管通过控制IN1和IN2的高低电平组合来决定电机正转、反转或停止ENA和ENB引脚用来使能PWM调速。逻辑关系如下表IN1/IN3IN2/IN4使能端电机状态LOWHIGHHIGH正转HIGHLOWHIGH反转LOWLOWHIGH刹车HIGHHIGHHIGH刹车任意任意LOW自由滑行接线上有个关键点L298N的GND必须和STM32的GND连接在一起这就是共地。不共地的话控制信号没有统一的参考电位电机要么不动要么乱转。我见过太多第一次做的人把这个忘了调了半天代码发现是接地问题。另外L298N的逻辑电源板载稳压输出5V和电机电源是分开的如果你用7.4V电池供电建议把跳线帽从5V使能输出上拔掉否则稳压片压力太大。PWM调速的实现我采用的是共阴极接法即ENA接STM32的PA0IN1和IN2分别接PA8和PA9。通过TIM2的PWM输出控制占空比IN1和IN2控制转向。这样四路IO口控制一个电机逻辑清晰。2.3 电机与编码器的连接规范TT电机和L298N的接线用杜邦线就行但要注意电机的两个接线端子没有极性定义随便接如果电机转向反了在软件里把那路IN交换就行不需要动线。唯一需要费点心思的是编码器的接线。编码器TT电机通常有6根线两根电机电源线两根编码器电源线5V和GND两根编码器信号线A相和B相。A相和B相输出的是正交方波信号通过检测相位差可以判断旋转方向通过计数脉冲可以算转速。虽然这次循迹避障未必用到测速但我还是推荐把编码器信号线引出到STM32的定时器输入捕获引脚比如PA6和PA7TIM3的CH1和CH2后面如果上PID速度闭环直接就能用。接线时编码器的5V和GND可以从L298N的5V输出取但注意共地。这里补充一个工程上的小技巧所有信号线走线尽量远离电机电源线尤其是编码器信号线和超声波ECHO信号线。电机转动时电刷会产生火花干扰形成电磁噪声如果信号线贴着电源线走很容易被干扰导致误触发。我在做的时候就把信号线整理到小车内层电源线走外层中间用扎带隔开实测超声波测距的稳定性明显好了很多。3. 底盘组装与传感器安装详解3.1 亚克力底盘的预钻孔与结构加固买到的亚克力底盘通常是一块板需要自己装铜柱、装电机支架。这一步看似简单但安装顺序错了容易返工。我的习惯是先把四个TT电机的固定支架用M3螺丝固定在底盘底面再装轮子。注意电机支架有方向区分固定后电机的输出轴应该指向底盘外侧轮子才能装上去。如果你把支架装反了轮子会和底盘摩擦跑起来会有很大的阻力声音。底盘组装还有一个经常被忽略的点亚克力板的保护膜不要急着撕。打孔和拧螺丝时保护膜能防止板面划伤等所有组件固定完毕再撕掉。另外铜柱的安装一定要加弹簧垫圈和螺母防松小车跑起来震动不小普通螺母很容易松脱。我见过有人跑着跑着轮子飞出去的就是因为固定电机的螺丝震松了。为了兼顾后续扩展我把控制板装在底盘的中间偏后位置电池盒装在底盘尾部正上方。这样重心大致居中车头略微上翘上坡时不容易卡住底盘前沿。循迹传感器支架则装在车头前方离地高度可以用铜柱调节保证传感器底面距离地面1-2cm左右这个距离非常关键。3.2 TCRT5000循迹传感器的原理与灵敏度调节TCRT5000是反射式光电传感器内部集成了一个红外发射管和一个光电接收管。工作时红外光从发射管射出照射到地面反射光被光电接收管接收。黑色物体吸光能力强反射光弱接收管输出高电平数字量输出为1白色物体反射光强接收管输出低电平数字量输出为0。就这么一个简单的原理构成了循迹的基本逻辑。安装时传感器面对地面离地高度很讲究。太高了红外光发散严重黑白线边界模糊太低了小车震动时传感器频频误触发。我实测下来1.5cm左右是最合适的这个高度下检测黑白线边界最清晰。调节板上的电位器可以改变比较器的阈值电压顺时针旋转减小阈值逆时针增大阈值判断标准是放在白纸上指示灯亮放在黑线上指示灯灭且边界分明。循迹传感器的安装位置也有讲究。如果是双路循迹两个传感器应分别安装在底盘前端的左右两侧间隔要比黑线的宽度略宽一点。比如赛道黑线宽2cm两个传感器中心间距最好在2.5-3cm之间。这样小车走直线时两个传感器都在黑线内压到线边时只有一个传感器触发就能判断应该往哪个方向转向。如果两个传感器间距太窄线稍微歪一点两个都触发方向判断就会混乱。3.3 HC-SR04超声波的安装与角度调整HC-SR04超声波模块的原理不复杂TRIG引脚给一个10us以上的高电平脉冲模块内部会自动发出8个40kHz的超声波脉冲同时把ECHO引脚拉高当收到回波时把ECHO引脚拉低。所以ECHO高电平的持续时间就是超声波从发射到返回的时间t距离可以用公式计算距离cm tus/58。这个公式很多人不理解为什么是58我解释一下。声速在空气中大约340m/s也就是每微秒0.034cm。超声波走的路程是发射到障碍物再反射回来实际距离是路程的一半所以距离 340 * t / 1000000 / 2 * 100换算成cm t * 0.017cm/us。换算成分数就是距离 t / 58.8取整就是除以58。这个公式非常常用建议直接背下来。超声波的安装位置我建议装在小车车头正前方高度大概在底盘上方8-10cm处用双面胶固定在亚克力板上。注意发射探头和接收探头之间不要被遮挡前面不要放任何障碍物。超声波模块的工作角度大概是15度左右所以它只能检测正前方障碍物。如果只在车头装一个侧面来的障碍物是检测不到的这个局限要想清楚。高级一点的做法是装一个舵机云台让超声波旋转扫描但这次作为一个入门项目固定安装就够用了。如果需要提高侧向检测能力可以在左右两侧各加一个红外避障模块做辅助。3.4 完整接线顺序与万用表检查所有模块安装到位后接下来是接线。我的接线顺序是先接电机电源线和电机信号线再接传感器电源和信号线最后接STM32的供电线和烧录线。这样如果接线过程中不小心短路也不会伤到主控。接线时优先使用不同颜色的杜邦线区分功能红色接电源黑色接GND黄色接PWM蓝色接信号线。颜色统一的好处是排查问题时一目了然。全部接完后先别急着上电。用万用表的蜂鸣器档测一下电源线和GND之间有没有短路这是最基础也是最重要的一步。很多人上来就插电池结果某个模块焊接短路直接把芯片烧了。然后上电用万用表依次检查电池电压是否为7.4V左右、L298N的5V输出是否为5V、降压模块输出是否为3.3V。确认各级电压正常后再单独测试每个模块的功能。这一步叫做分模块上电调试是嵌入式开发里非常标准的工作流程。4. 上篇制作过程中的常见坑与排查实录4.1 电机不转或只有一个轮子转这是遇到频率最高的问题排查思路其实很固定。先用万用表测L298N的12V输入是否有电压再测5V逻辑电源是否正常然后测ENA和ENB是否有PWM信号。如果都有就用短接线把某个IN引脚直接接高电平看电机是否转。这样一级一级排除基本十分钟能定位问题。常见的原因有三个一是共地没共好信号参考地不一致二是ENA跳线帽没插PWM使能端悬空三是杜邦线接触不良TT电机的母座端子比较松插的时候没插到底。4.2 循迹传感器灵敏度不稳定循迹传感器装好后会出现白纸上指示灯不亮或者黑线上指示灯还亮的情况。这种基本都是电位器没调对。我的建议是先把小车放在白纸区域慢慢顺时针旋电位器到指示灯刚好熄灭的位置再往回旋一点点使其处于临界状态。然后把小车挪到黑线上确认指示灯亮起。如果亮起的边界还不够清晰再微调。还有一个容易被忽略的点是环境光干扰即使TCRT5000发射的是红外光强烈的太阳光中也含有红外成分会导致检测结果漂移所以测试最好在室内固定光源环境下进行。4.3 超声波测距数据乱跳超声波数据跳动大部分原因不是代码问题而是电气干扰和安装问题。首先检查ECHO引脚的杜邦线是否与电机电源线扎在一起如果扎在一起分开或者换根屏蔽线试试。其次TRIG引脚的高电平持续时间要严格大于10us有些人用HAL库的延时函数因为HAL_Delay最小单位是1ms直接用会导致超声波模块无法正常触发。正确做法是用for循环或者定时器微秒延时函数。最后超声波模块前面如果有其他传感器支架或螺丝头遮挡也会造成回波干扰检查模块前方是否有金属物体。4.4 STM32板子反复重启STM32最小系统板反复重启最常见的两个原因一是TPX570芯片的复位引脚受到干扰导致不断复位。排查方法是把ST-Link的复位线拔掉看是否恢复正常如果恢复就是调试器复位信号干扰。二是电源纹波过大电机启动瞬间电流拉低电压导致欠压复位。解决方法是给STM32单独供电或加一个大容量的电解电容470uF或1000uF并联在电源输入端。我实测加了电容之后即使电机频繁正反转系统也稳定了。这个经验适用于几乎所有单片机小车项目属于项目进阶必备的经典伎俩。4.5 Keil工程配置的两个关键坑最后补充一个开发环境相关的经验。用Keil建STM32F103C8T6工程时在Target选项卡里要把芯片型号选对否则烧录时Flash算法不匹配。另外在C/C选项卡的Define一栏要填上STM32F10X_MD这是中容量产品的宏定义不写的话标准外设库会默认成小容量或者大容量可能导致引脚复用配置出错。我见过不少人烧录成功但程序跑飞就是这个宏定义没写对。另外Debug设置里要选择ST-Link Debugger并配置正确的Flash Download地址C8T6的Flash起始地址固定是0x08000000大小64KB这些填错也会烧录失败。还有一个小提醒烧录时如果ST-Link连接不上芯片先按一下板子上的复位键再试有时候芯片停在待机状态或者看门狗溢出复位一下就能恢复了。做小车这个项目的乐趣在于它不像纯软件项目那样调试完只能盯着屏幕看而是一个实体不断跟你互动的过程。写代码只是一部分真正的难点在于把硬件和软件完美地协调起来。上篇我把第1点到第3点讲完了现在你的小车应该已经有了一个完整的硬件躯壳电源系统、电机驱动、传感器也都就位了。下篇我会详细拆解CubeMX的初始化配置、循迹避障的核心算法逻辑以及怎么把PID调速加进去让小车从能走到走得稳、走得准。如果你在上篇的任何一个环节卡住了欢迎在评论区把现象描述出来我会根据自己的经验给你一些排查建议。