1. 项目概述与硬件选型第一次接触STM32蓝牙遥控小车时我被这个项目深深吸引。它不仅融合了嵌入式开发的核心技术还能让我们亲手打造一个会动的智能玩具。相比常见的51单片机方案STM32F103ZET6这颗Cortex-M3内核的芯片性能更强外设资源更丰富特别适合用来学习现代嵌入式开发。我在材料选择上走了些弯路这里分享我的实战经验。核心控制器选用正点原子的精英开发板它自带调试接口和丰富的外设引脚。电机驱动模块推荐L298N这个经典的双H桥驱动芯片最大能输出2A电流驱动普通小车电机绰绰有余。蓝牙模块我用的是HC-06价格便宜且兼容性强手机装上串口调试APP就能直接控制。电源部分要特别注意12V锂电池给L298N供电再通过LM2596降压模块得到5V给开发板和舵机供电。这里有个坑我踩过——如果直接用开发板的USB供电电机启动时电压会被拉低导致单片机复位。所以一定要给电机驱动单独供电记得所有模块的GND要共地。2. 硬件连接详解接线是项目成功的关键我画了张简化连接图帮助理解。L298N模块有四个输入引脚IN1-IN4分别接到STM32的PF0-PF3。这组GPIO要配置为推挽输出模式记得在代码里开启APB2时钟。舵机信号线接PC6这个引脚要复用为TIM3的通道1输出PWM波。蓝牙模块的连接最让人困惑。HC-06的TXD接STM32的PA10USART1_RXRXD接PA9USART1_TX。初次使用时要用AT命令配置模块名称和密码我建议先用USB转TTL模块调试好蓝牙参数再接入STM32系统。实际组装时这些细节要注意电机线要用热缩管绝缘避免短路L298N的散热片会发热不要贴在其他元件上舵机安装要确保转向轴与车轮平行所有电源线先不接用万用表确认电压正常再通电3. 电机驱动开发实战控制直流电机正反转的逻辑其实很简单但STM32的库函数配置容易出错。在motor.c里我定义了六个基本函数正转、反转和停止。关键是要理解L298N的真理表IN10, IN21 → 电机正转IN11, IN20 → 电机反转IN1IN2 → 电机刹车GPIO初始化时容易漏掉时钟使能这里给出完整代码void Motor_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); GPIO_InitStruct.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOF, GPIO_InitStruct); // 初始状态全部拉低 GPIO_ResetBits(GPIOF, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3); }调试时发现电机有时不响应原来是没加延时。在正反转切换时要插入10ms延时避免H桥瞬间短路。后来我改用定时器中断来管理电机时序运行更稳定。4. PWM舵机控制技巧转向舵机控制是项目的难点之一。MG995舵机需要50Hz的PWM信号对应周期20ms。控制脉宽在0.5ms-2.5ms之间变化就能实现0-180度旋转。TIM3的配置参数要仔细计算TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_InitStruct.TIM_Period 199; // ARR值 TIM_InitStruct.TIM_Prescaler 7199; // 72MHz/(71991)10kHz TIM_InitStruct.TIM_ClockDivision 0; TIM_InitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, TIM_InitStruct);设置比较寄存器CCR1的值可以改变占空比。实测发现CCR15 → 0.5ms脉宽左转极限CCR115 → 1.5ms脉宽中间位置CCR225 → 2.5ms脉宽右转极限舵机安装后要做机械校准。我专门写了个测试程序让舵机在三个关键位置来回切换同时用量角器确认实际转向角度。5. 蓝牙通信协议解析HC-06模块默认波特率是9600但为了传输效率我设为115200。在usart.c中初始化USART1时要注意GPIO和NVIC的配置USART_InitTypeDef USART_InitStruct; USART_InitStruct.USART_BaudRate 115200; USART_InitStruct.USART_WordLength USART_WordLength_8b; USART_InitStruct.USART_StopBits USART_StopBits_1; USART_InitStruct.USART_Parity USART_Parity_No; USART_InitStruct.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStruct);手机端我推荐蓝牙串口助手APP可以自定义按键发送十六进制数据。在main.c中通过判断接收到的字节来执行相应动作if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) { uint8_t cmd USART_ReceiveData(USART1); switch(cmd) { case 0x01: motor_forward(); break; case 0x02: motor_backward(); break; // 其他命令处理... } }遇到数据丢失的问题时我增加了环形缓冲区来存储接收数据并通过中断方式处理再也没出现过丢包现象。6. 系统整合与调试当所有模块单独测试通过后整合时又遇到了新问题。首先是电源干扰电机启动导致单片机复位。解决方法是在电源输入端加了大容量电解电容并在程序启动时加入了软启动逻辑。另一个坑是PWM和电机控制的时序冲突。最初舵机转向时电机会卡顿后来发现是TIM3中断优先级设置问题。通过NVIC调整中断优先级后两个外设就能和谐共处了。调试时这个小技巧很实用用LED指示当前状态如蓝牙连接成功亮蓝灯蜂鸣器发出不同声音提示错误类型通过串口打印实时调试信息最终的主控制逻辑采用状态机设计定义了五种运行模式待机模式等待蓝牙连接手动遥控模式自动避障模式需加装超声波模块校准模式故障保护模式7. 性能优化与扩展基础功能实现后我做了这些优化加入加速度控制用定时器逐渐改变PWM占空比让启动/停止更平缓增加PID控制算法使转向更精准添加低电压保护监测电池电压低于10.5V时自动停车如果想进一步提升可以考虑改用HC-05蓝牙模块支持主从模式增加MPU6050实现姿态控制添加OLED显示屏显示状态信息移植FreeRTOS实现多任务管理这个项目最让我有成就感的是当小车第一次按照手机指令灵活运动时所有调试时的挫败感都烟消云散了。建议大家在面包板上先搭建原型功能验证后再制作PCB。完整工程代码我已经整理好包含详细注释和调试记录需要的小伙伴可以私信我。