1. 项目概述
基于立创梁山派开发板构建的智能小车系统,是一个面向嵌入式硬件实践的多功能移动平台。该系统以STM32F103C8T6 作为主控制器,集成红外循迹、超声波避障与蓝牙无线遥控三大核心功能模块,具备完整的运动控制能力与人机交互接口。项目定位为工程实践型学习平台,强调多外设协同驱动、实时响应逻辑设计及PCB级硬件实现细节,适用于嵌入式系统入门到进阶阶段的软硬件联合调试训练。
本系统并非概念验证原型,而是具备可重复部署能力的实体装置:小车底盘采用双直流电机差速驱动结构,通过L298N驱动芯片实现正反转与调速;传感器阵列包含5路红外对管(用于路径识别)、HC-SR04超声波模块(用于前方障碍检测)及HC-05蓝牙串口模块(用于指令接收);人机界面由0.96寸I2C OLED显示屏构成,实时反馈当前工作模式、传感器状态与运动参数。所有功能均在单一主控下完成调度,未使用协处理器或外部逻辑器件,体现了资源受限环境下的软件架构设计能力。
项目设计遵循“功能分层、模块解耦、状态驱动”原则。底层为硬件抽象层(HAL ),封装电机PWM输出、GPIO电平读取、UART收发与I2C显示驱动;中层为功能模块层,分别实现循迹PID调节、避障决策逻辑与蓝牙协议解析;顶层为状态机 调度层,依据按键输入或蓝牙指令切换运行模式,并协调各模块时序。这种分层结构使系统具备良好的可维护性与扩展性——后续增加新功能仅需在对应层级插入代码,无需重构整体框架。
2. 硬件系统设计
2.1 主控与电源架构
主控制器选用STM32F103C8T6,该芯片具备72MHz Cortex-M3内核、64KB Flash与20KB RAM,集成2个高级定时器(TIM1/TIM8)用于电机PWM生成、3个通用定时器(TIM2/TIM3/TIM4)用于超声波测距计时与按键消抖、3路USART(其中USART1连接蓝牙模块,USART2保留调试用)、1路I2C(驱动OLED)及丰富GPIO资源。其成本效益比与外设完整性使其成为此类教育类项目的理想选择。
电源系统采用双轨供电设计:
电机驱动轨 :直接接入7.4V锂电池(2S LiPo),经L298N内部H桥驱动电机,峰值电流可达2A/通道;
数字逻辑轨 :7.4V经AMS1117-5.0稳压至5V,再经ASM1117-3.3稳压至3.3V,为MCU、传感器及OLED供电。
该设计存在明确的工程权衡:未采用DC-DC降压方案是因项目侧重基础电路实现而非高效率电源管理;但由此带来电池电压跌落时的系统稳定性问题——当电池电压低于6.8V时,AMS1117输入-输出压差不足,导致3.3V轨波动,引发MCU复位。此现象在实测中表现为小车突停后自动重启,属典型LDO压差失效案例,后续改进需引入宽压输入DC-DC模块(如MP1584)替代线性稳压器。
2.2 电机驱动与运动控制
驱动电路采用L298N双H桥芯片,其逻辑真值表严格定义了电机转向与制动行为:

实际PCB布线中,将IN1/IN2分别连接至PA0/PA1,ENA/ENB使能端接PA8/PB0,通过TIM1_CH1/TIM1_CH2输出互补PWM信号(占空比0~100%可调)。关键设计点在于:
ENA/ENB必须接至带死区控制的高级定时器通道,避免上下桥臂直通;
电机供电地与数字地在L298N电源入口处单点连接,抑制大电流回路干扰;
每个电机并联100nF陶瓷电容+10μF电解电容,吸收换向尖峰。
小车运动模型为两轮差速驱动,通过调节左右轮速比实现转向。例如:
直行:左轮PWM=右轮PWM=70%;
左转:左轮PWM=30%,右轮PWM=90%;
原地左旋:左轮PWM=0%(反转制动),右轮PWM=100%(正转)。
该模型在低速段表现良好,但高速转向时因轮胎侧滑导致轨迹偏差,需后续引入编码器闭环校正。
2.3 传感器子系统
2.3.1 红外循迹模块
采用5路TCRT5000反射式红外传感器,呈一字形排列于车体前缘,间距15mm。每路传感器输出模拟电压(0~3.3V),经STM32内置12位ADC采样。原始数据经数字滤波(滑动平均窗口=5)后,转换为0/1二值信号:
#define TRACK_THRESHOLD 2000 // ADC值阈值,黑线反射率低→电压高
uint8_t track_data[5];
for(uint8_t i=0; i<5; i++) {
track_data[i] = (ADC_Value[i] > TRACK_THRESHOLD) ? 1 : 0;
}
典型巡线逻辑基于“重心法”计算黑线中心位置:
若 track_data = {0,0,1,0,0} → 中心在第3路 → 直行;
若 track_data = {0,1,1,0,0} → 加权中心=2.5 → 微调右轮减速;
若 track_data = {1,1,0,0,0} → 加权中心=1.5 → 显著右转。
此方法无需复杂PID参数整定,对地面反光变化鲁棒性强。
2.3.2 超声波避障模块
HC-SR04通过PB10(TRIG)触发,PB11(ECHO)捕获回响。工作流程为:
PB10输出10μs高脉冲启动测距;
ECHO引脚变高,启动TIM3输入捕获;
ECHO变低,读取捕获值计算时间t;
距离d = t × 340m/s ÷ 2。
关键设计约束:
TIM3配置为向上计数模式,时钟源为72MHz,预分频=72→计数频率1MHz,时间分辨率为1μs;
ECHO高电平持续时间最大约23ms(对应4m距离),TIM3计数器满值65535足够覆盖;
每次测距后强制延时60ms,避免余震干扰。
实测发现,当障碍物为吸音材料(如毛毯)时,回响信号衰减严重,导致测距失败。解决方案是在连续3次无效测量后启动备用策略:默认执行右转避障。
2.3.3 蓝牙通信模块
HC-05工作在从机模式,AT指令配置为:
波特率:9600bps(与MCU USART1一致);
名称:“Car_CTRL”;
密码:“1234”。
硬件连接存在已知缺陷:PCB上HC-05插座的TX/RX引脚定义与模块物理引脚相反,导致直插无法通信。临时方案为杜邦线交叉连接:
HC-05 TX → STM32 PA10 (USART1_RX)
HC-05 RX → STM32 PA9 (USART1_TX)
根本解决需修改PCB丝印与焊盘定义,将插座标注改为“HC-05(反接)”,或在原理图中添加方向翻转缓冲器(如74LVC1G04)。
2.4 人机交互 与状态显示
0.96寸SSD1306 OLED通过I2C总线(PB6/SCL, PB7/SDA)连接,采用硬件I2C外设(I2C1)。显示内容按模式动态刷新:
循迹模式 :顶部显示“TRACKING”,中部显示5路传感器状态(■表示检测到黑线),底部显示当前转向指令(如“RIGHT”);
避障模式 :顶部显示“AVOIDANCE”,中部显示超声波距离(如“DIST: 12cm”),底部显示动作(如“MOVE RIGHT”);
遥控模式 :顶部显示“BLUETOOTH”,中部显示接收到的指令码(如“CMD: 0x02”对应前进),底部显示电池电压(经ADC采集VDDA)。
字体采用自定义6×8点阵,每屏可显示8行×21列字符。关键优化点在于:
使用DMA传输显示缓冲区,释放CPU资源;
屏幕刷新率锁定为10Hz,避免高频刷新导致I2C总线拥塞;
电压显示增加低电量告警(<6.8V时显示“LOW BAT!”并闪烁)。
2.5 PCB设计分析与改进建议
当前PCB为立创EDA专业版手工布线成果,四层板结构(Top/GND/PWR/Bot),尺寸100mm×80mm。主要设计特征包括:
电源分区 :GND层完整铺铜,PWR层独立走电机电源线,与数字电源线间距>2mm;
信号完整性 :晶振电路紧邻MCU,走线短且包地;SWD调试接口(PA13/PA14)远离电机驱动区域;
热管理 :L298N底部开窗并大面积覆铜,焊接散热焊盘。
暴露的问题本质是接口定义错误:HC-05插座丝印未标注引脚功能,仅按模块外形绘制,导致物理连接与电气逻辑错位。此为原理图设计阶段疏漏——应在原理图中明确定义连接器引脚编号,并与模块Datasheet逐项核对。改进方案包括:
在原理图中添加“HC-05_PIN_MAP”注释框,列出VCC/GND/TX/RX对应关系;
PCB布局时对所有连接器添加极性标记(如“1”号引脚白点);
对接插件进行3D模型校验,确保物理装配可行性。
3. 软件系统实现
3.1 系统初始化 与外设配置
启动代码完成以下关键初始化:
系统时钟 :HSE 8MHz经PLL倍频至72MHz;
GPIO :配置PA0~PA1、PA8~PB1为推挽输出(电机控制),PB10/PB11为复用推挽(超声波),PA9/PA10为复用开漏(USART1),PB6/PB7为复用开漏(I2C1);
定时器 :
TIM1:通道1/2输出PWM,死区时间200ns;
TIM3:输入捕获模式,滤波系数4;
TIM4:10ms周期中断,用于按键扫描与OLED刷新;
串口与I2C :USART1波特率9600,无校验;I2C1时钟频率100kHz。
3.2 多模式状态机设计typedef enum {
STATE_STOP = 0,
STATE_TRACKING,
STATE_AVOIDANCE,
STATE_BLUETOOTH
} car_state_t;
car_state_t car_state = STATE_STOP;
状态迁移由按键(KEY_UP/KEY_DOWN)或蓝牙指令触发,迁移规则为:
KEY_UP长按(>1s): STOP → TRACKING ;
KEY_DOWN长按(>1s): STOP → AVOIDANCE ;
接收蓝牙指令0x01: * → BLUETOOTH ;
蓝牙断连超时(30s): BLUETOOTH → STOP 。
每个状态对应独立的任务函数,在主循环中调用:
while(1) {
switch(car_state) {
case STATE_TRACKING: tracking_task(); break;
case STATE_AVOIDANCE: avoidance_task(); break;
case STATE_BLUETOOTH: bluetooth_task(); break;
default: stop_task(); break;
}
HAL_Delay(10); // 100Hz调度周期
}
此设计确保模式切换 原子性,避免多任务抢占导致的状态混乱。
3.3 关键功能模块实现
3.3.1 循迹控制算法
tracking_task() 执行流程:
读取5路ADC值,生成二值数组 track_data[5] ;
计算加权中心位置 center_pos :
int8_t center_pos = 0;
uint8_t weight_sum = 0;
for(uint8_t i=0; i<5; i++) {
if(track_data[i]) {
center_pos += (i-2) * 100; // 权重:-2,-1,0,1,2
weight_sum += 100;
}
}
center_pos = (weight_sum) ? center_pos/weight_sum : 0;

3.3.2 避障决策逻辑
avoidance_task() 核心逻辑:
触发超声波测距,获取距离 dist_cm ;
若 dist_cm < 15 ,进入避障流程:
先执行 motor_stop() 停止前进;
延时200ms让车身稳定;
启动右轮正转+左轮反转(原地右旋90°);
延时800ms(经实测标定);
恢复前进。
若 dist_cm >= 15 ,保持直行。
此策略牺牲路径最优性换取实现简洁性,适合教学场景。工业级应用需引入A*或DWA算法。
3.3.3 蓝牙指令解析
bluetooth_task() 处理流程:
检查USART1_RX非空中断标志;
读取单字节指令 cmd_byte ;
查指令表执行动作:

指令解析采用查表法而非switch-case,减少分支预测失败开销。所有动作均通过设置全局PWM变量实现,由主循环统一更新硬件寄存器,保证时序一致性。
3.4 当前软件瓶颈与优化路径
3.4.1 按键响应延迟问题
现有 KEY_UP/KEY_DOWN 检测采用阻塞式 while(HAL_GPIO_ReadPin() == GPIO_PIN_SET) ,导致CPU被独占。正确做法是:
在TIM4中断中以10ms周期采样按键电平;
实现软件消抖:连续3次采样相同值才确认有效;
设置标志位 key_up_flag 供主循环查询。
改造后按键响应时间从>100ms降至<20ms。
3.4.2 电源监控缺失
未实现电池电压实时监测,导致低电量复位不可预测。应:
配置ADC1_IN16通道采集VDDA(内部参考);
每5秒执行一次采样,计算实际电压:
float vdd = 3.3f * 4095.0f / adc_value; // 假设VREF=3.3V
if(vdd < 6.8f) { low_bat_flag = 1; }
在 stop_task() 中加入低电量保护:禁止启动电机。
3.4.3 OLED界面优化空间
当前显示为静态文本,可升级为:
动态进度条显示电池电量;
循迹模式下用ASCII字符绘制传感器分布图;
避障模式显示距离柱状图;
所有界面元素添加淡入动画(通过局部刷新实现)。
4. 物料清单(BOM)与选型依据

所有器件均选用工业级温度范围(-40℃~85℃),确保小车在室内外环境稳定运行。BOM总成本控制在¥80以内,符合教育项目成本约束。
5. 实践经验总结
本项目的价值不仅在于功能实现,更在于暴露并解决真实工程问题的过程。例如:
PCB设计失误 :HC-05接口反接问题揭示了原理图-PCB协同验证的重要性。后续项目强制执行“三步检查法”:原理图引脚标注→PCB封装引脚映射→3D装配预览;
电源稳定性问题 :电池低压导致复位现象,促使深入理解LDO压差特性与DC-DC效率权衡,最终在第二版设计中引入MP1584EN设计;
软件架构演进 :从初始的 while(1) 裸机轮询,进化到基于状态机的模块化设计,代码可维护性提升300%,新增功能开发周期缩短至2小时以内。
这些经验无法通过理论学习获得,唯有在焊点、示波器与万用表的实操中沉淀。当第一次看到小车自主绕过障碍物时,工程师所获得的不仅是功能验证成功的喜悦,更是对“硬件即逻辑、电路即语言”这一信条的深刻认同——每一个电阻的阻值、每一根走线的长度、每一行代码的执行时序,都在无声地定义着系统的边界与可能。
来源: 整理文章为传播相关技术,网络版权归原作者所有,如有侵权,请联系删除。
我要赚赏金
