STM32F103RC+L298N+五路红外,手把手教你从零搭建循迹小车(附完整代码)
STM32F103RC与L298N驱动的五路红外循迹小车全流程实战指南刚接触嵌入式开发时第一个能跑起来的实物项目往往最能点燃学习热情。而循迹小车正是这样一个完美的新手项目——它融合了GPIO控制、PWM调速、传感器数据处理等核心技能又能在桌面上直观展现运行效果。本文将用STM32F103RC作为主控配合L298N电机驱动模块和五路红外传感器带你从元器件选型到代码调试完整实现一个可适应复杂路径的智能循迹小车。1. 硬件选型与电路设计1.1 核心器件选型要点主控芯片选择STM32F103RC主要基于三点考量充足的GPIO资源五路传感器输入四路PWM输出内置多个定时器TIM2/TIM3用于电机控制性价比优势Cortex-M3内核满足需求且价格亲民电机驱动模块采用L298N的双H桥设计时需注意驱动电压范围7-35V建议选择12V锂电池组单路持续输出电流2A峰值可达3A内置5V稳压输出可为单片机供电提示购买L298N模块时建议选择带光耦隔离的版本能有效减少电机干扰导致的单片机复位。五路红外循迹传感器的关键参数对照参数项典型值说明检测距离1-3cm可通过电位器调节输出方式数字量0/1白线反射时为高电平工作电压3.3-5V需与STM32电平匹配响应时间1ms满足实时控制需求1.2 电源系统设计多电压供电是稳定运行的基础[12V锂电池] → [L298N Vin] ├─[5V稳压输出] → [STM32供电] └─[7.4V降压模块] → [红外传感器供电]常见问题排查电机启动时单片机重启 → 检查地线共接与电源滤波电容传感器误检测 → 测量实际供电电压是否稳定PWM输出异常 → 确认定时器时钟配置正确2. 开发环境搭建与工程配置2.1 工具链准备推荐使用Keil MDK-ARM开发环境安装Keil uVision5需注册获取license下载STM32F1xx_DFP设备支持包配置ST-Link/V2调试器驱动关键工程设置# 在Options for Target中确认 Target → Xtal(MHz) 8.0 C/C → Define: STM32F10X_MD, USE_STDPERIPH_DRIVER Debug → ST-Link Debugger2.2 外设初始化代码解析GPIO输入配置红外传感器void Track_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStruct.GPIO_Mode GPIO_Mode_IPU; // 上拉输入 GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStruct); }PWM输出配置电机控制void PWM_Init(TIM_TypeDef* TIMx, uint16_t Channel) { TIM_OCInitTypeDef TIM_OCInitStruct; TIM_OCInitStruct.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStruct.TIM_OCPolarity TIM_OCPolarity_High; TIM_OCInitStruct.TIM_Pulse 0; // 初始占空比为0 switch(Channel) { case 1: TIM_OC1Init(TIMx, TIM_OCInitStruct); break; case 2: TIM_OC2Init(TIMx, TIM_OCInitStruct); break; case 3: TIM_OC3Init(TIMx, TIM_OCInitStruct); break; case 4: TIM_OC4Init(TIMx, TIM_OCInitStruct); break; } TIM_CtrlPWMOutputs(TIMx, ENABLE); }3. 运动控制算法实现3.1 电机驱动逻辑L298N的两种控制方式对比控制模式IN1IN2电机状态正转高低顺时针反转低高逆时针刹车高高快速停止滑行低低惯性停止对应代码实现void Motor_Control(MotorSide side, int16_t speed) { speed constrain(speed, -MAX_SPEED, MAX_SPEED); if(side LEFT) { if(speed 0) { GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET); // IN1 GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET); // IN2 TIM_SetCompare3(TIM3, speed); } else { GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_RESET); GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET); TIM_SetCompare3(TIM3, -speed); } } // 右电机控制同理... }3.2 循迹策略优化五路传感器的状态组合与对应动作传感器状态二进制处理策略●●●●●11111停车到达终点●●○●●11011直行全速前进●●●○●11101轻微左转右轮加速20%●●○○●11001中度左转右轮加速40%●○○○●10001急左转左轮反转●○●●●10111轻微右转左轮加速20%○○●●●00111中度右转左轮加速40%○○○●●00011急右转右轮反转○○○○○00000停车检查可能脱轨状态机实现代码void Track_StateMachine(void) { static uint8_t last_state 0; uint8_t current_state Get_Sensor_State(); if(current_state last_state) return; switch(current_state) { case 0b11011: // 直行 Motor_SetSpeed(BASE_SPEED, BASE_SPEED); break; case 0b11101: // 轻微左转 Motor_SetSpeed(BASE_SPEED*0.8, BASE_SPEED*1.2); break; // 其他状态处理... default: if(last_state ! 0) Motor_SetSpeed(0, 0); // 异常停止 } last_state current_state; }4. 调试技巧与性能优化4.1 常见问题解决方案传感器调试步骤用万用表测量各传感器输出电平白纸上应为高电平3V黑胶带上应为低电平0.5V调节传感器板上电位器顺时针增大检测距离逆时针减小检测距离固定高度测试最佳距离通常为1-1.5cmPWM频率选择建议直流电机5-20kHz避免可闻噪声过高频率会导致驱动芯片发热推荐配置// 72MHz主频预分频72-1ARR100-1 → 10kHz TIM_TimeBaseStructure.TIM_Prescaler 71; TIM_TimeBaseStructure.TIM_Period 99;4.2 高级优化方向PID控制算法引入typedef struct { float Kp, Ki, Kd; float integral; float last_error; } PID_Controller; float PID_Update(PID_Controller* pid, float error) { float derivative error - pid-last_error; pid-integral error; pid-last_error error; return pid-Kp * error pid-Ki * pid-integral pid-Kd * derivative; } // 应用示例 PID_Controller left_pid {0.5, 0.01, 0.2}; float error target_position - sensor_read; float adjustment PID_Update(left_pid, error); Motor_SetSpeed(BASE_SPEED adjustment, BASE_SPEED);抗干扰设计电源滤波在电机供电端并联1000μF电解电容0.1μF陶瓷电容信号隔离高速光耦隔离PWM控制信号软件滤波对传感器输入进行移动平均滤波#define FILTER_WINDOW 5 uint8_t sensor_filter[FILTER_WINDOW] {0}; uint8_t Filter_Input(uint8_t new_val) { static uint8_t index 0; sensor_filter[index] new_val; index (index 1) % FILTER_WINDOW; uint8_t sum 0; for(uint8_t i0; iFILTER_WINDOW; i) { sum sensor_filter[i]; } return (sum FILTER_WINDOW/2) ? 1 : 0; }完成基础功能后可以尝试扩展蓝牙遥控、OLED状态显示或迷宫探索算法。调试时建议先用USB供电测试逻辑功能再接入电机电源进行实际运行测试。遇到电机干扰问题时重点检查地线布局和电源退耦电容的安装位置。