用STC89C52和HC-06蓝牙模块,从零组装一台能手机遥控的循迹小车(附完整代码)

张开发
2026/4/12 3:44:51 15 分钟阅读

分享文章

用STC89C52和HC-06蓝牙模块,从零组装一台能手机遥控的循迹小车(附完整代码)
从零打造STC89C52蓝牙循迹小车硬件选型到代码实战全解析当你想把一堆电子元件变成能听话跑动的智能小车时STC89C52这颗经典51单片机绝对是性价比之选。我去年带学生做课设时发现用蓝牙遥控自动循迹的方案既能练手基础电路又能玩转串口通信和传感器融合——关键是成本能控制在百元内。下面就把从元器件采购到PID调参的全流程拆解给你看。1. 硬件清单与电路设计1.1 核心器件选型建议采购前先确认你的作战指挥部器件类型推荐型号单价范围备注主控STC89C52RC5-8元建议买DIP40封装蓝牙模块HC-06从机模块15-25元注意区分主从模式电机驱动L298N双H桥8-12元带散热片版本更可靠循迹传感器TCRT50001.5元/个通常需要3-5个直流电机N20减速电机10-15元建议配1:48减速比电源管理AMS1117-5.00.5元需配合18650电池使用实战经验电机驱动选L298N而不是TB6612虽然后者效率更高但L298N的散热性能在调试阶段更耐折腾。去年有组学生连续烧了3个TB6612后才听劝换方案。1.2 电路连接要点核心电路搭建要特别注意这些接口// 典型引脚定义(根据实际接线修改) sbit IN1 P1^0; // 右电机正极 sbit IN2 P1^1; // 右电机负极 sbit IN3 P1^2; // 左电机正极 sbit IN4 P1^3; // 左电机负极 sbit SEN_L P2^0; // 左侧循迹传感器 sbit SEN_R P2^1; // 右侧循迹传感器警告蓝牙模块的TXD/RXD需要交叉连接单片机即HC-06的TXD接P3.0(RXD)RXD接P3.1(TXD)。接反会导致通信失败但不会损坏设备。红外传感器布局推荐这种前三角阵列[SEN_L] [SEN_M1] [SEN_M2] [SEN_R]中间两个传感器间距建议1.5-2cm具体根据赛道黑线宽度调整。2. 蓝牙通信框架搭建2.1 HC-06配置技巧新模块到手先用AT命令设置ATNAMEBluetooth_Car // 修改设备名 ATPIN1234 // 设置配对密码 ATBAUD4 // 9600bps(11200,22400,...,49600)手机端推荐使用蓝牙串口助手APP发送字符指令可这样定义F - 前进 B - 后退 L - 左转 R - 右转 A - 自动循迹模式 S - 紧急停止2.2 串口中断服务程序用中断方式处理蓝牙数据更可靠void UART_ISR() interrupt 4 { if(RI) { RI 0; // 清除接收标志 char cmd SBUF; switch(cmd) { case F: motor_run(FORWARD); break; case B: motor_run(BACKWARD); break; case L: motor_run(TURN_LEFT); break; case R: motor_run(TURN_RIGHT); break; case A: mode AUTO_MODE; break; case S: motor_stop(); break; } } }记得初始化时配置定时器1为模式2自动重装void UART_Init() { SCON 0x50; // 模式1,允许接收 TMOD | 0x20; // 定时器1模式2 TH1 0xFD; // 9600bps11.0592MHz TR1 1; ES 1; // 开启串口中断 EA 1; // 全局中断使能 }3. 循迹算法实现3.1 基础阈值检测法先读取传感器状态矩阵#define LINE_DETECTED 0 // TCRT5000遇到黑线输出低电平 void read_sensors() { sensor_state[0] (SEN_L LINE_DETECTED); sensor_state[1] (SEN_M1 LINE_DETECTED); sensor_state[2] (SEN_M2 LINE_DETECTED); sensor_state[3] (SEN_R LINE_DETECTED); }简单逻辑判断void line_following() { if(sensor_state[0] !sensor_state[3]) { // 左侧检测到黑线 motor_run(TURN_LEFT); } else if(!sensor_state[0] sensor_state[3]) { // 右侧检测到黑线 motor_run(TURN_RIGHT); } else { // 中间传感器在黑线上 motor_run(FORWARD); } }3.2 进阶PID控制对于复杂赛道需要引入PID算法float Kp0.6, Ki0.01, Kd0.2; // 需实际调试 float error0, last_error0, integral0; void PID_Control() { // 计算误差(假设用3个传感器) error -1*sensor_state[0] 0*sensor_state[1] 1*sensor_state[2]; integral error; float derivative error - last_error; float output Kp*error Ki*integral Kd*derivative; // 转换为电机PWM set_motor_speed(LEFT_MOTOR, base_speed output); set_motor_speed(RIGHT_MOTOR, base_speed - output); last_error error; }调试技巧先调Kp直到小车能快速响应但不过冲再调Kd抑制振荡最后微调Ki消除静态误差4. 电机驱动与电源管理4.1 L298N驱动配置典型驱动电路连接方式IN1 - P1.0 IN2 - P1.1 IN3 - P1.2 IN4 - P1.3 ENA - 5V(常使能) ENB - 5V(常使能)电机控制真值表IN1IN2电机状态10正转01反转11刹车00滑行停止4.2 低功耗优化当使用18650电池供电时void power_save() { PCON | 0x01; // 进入空闲模式 // 通过蓝牙接收中断唤醒 }实测电流对比正常运行~300mA空闲模式5mA掉电模式0.1mA(但需外部中断唤醒)5. 完整工程代码架构推荐采用模块化组织/main.c // 主循环和初始化 /uart.c // 蓝牙通信 /motor.c // 驱动控制 /line_sensor.c // 循迹算法 /config.h // 引脚定义和参数配置关键数据结构示例typedef enum { MANUAL_MODE, AUTO_MODE, CALIBRATION_MODE } SystemMode; typedef struct { uint8_t speed_left; uint8_t speed_right; SystemMode current_mode; } CarState;在Keil中编译时注意设置Memory Model为Small勾选Create HEX File建议开启代码优化Level 26. 调试与问题排查常见故障处理指南现象可能原因解决方法蓝牙无法连接波特率不匹配检查AT命令设置的波特率电机单侧不转L298N使能端接触不良用万用表测量ENA/ENB电压循迹时频繁抖动PID参数过于激进适当减小Kp或增大Kd运行一段时间后复位电源电流不足并联电容或在电机端加104瓷片电容烧录程序时如果提示检测不到单片机先冷启动断电后点击下载再上电检查CH340驱动是否安装确保P1.0/P1.1没有接外部上拉最后分享一个真实案例去年有组同学的小车总在弯道冲出赛道后来发现是传感器安装高度过高。用卡尺测量后调整到距地面8mm问题立即解决。这提醒我们——硬件调试有时比代码更重要。

更多文章