51单片机循迹避障小车:STC89C52+L298N驱动与传感器方案
2026/9/17 14:39:24 网站建设 项目流程

简介:基于STC89C52单片机与L298N驱动芯片的智能循迹避障小车毕设/课设文档资料,适合电子信息、自动化等专业学生用于课程设计、毕业设计或单片机入门实践。内容覆盖系统方案论证、硬件电路设计、软件流程与调试方法,重点讲解红外对管检测黑线与障碍物、L298N电机驱动及PWM调速实现,可帮助读者快速搭建完整的小车控制系统。压缩包内共1个doc文档,约434KB,包含摘要、绪论、方案设计、硬件设计、软件设计、安装调试及参考文献等完整章节,目录结构清晰,便于按模块查阅。目前已有541人学习下载。文档对STC89C52单片机特性、L298N驱动原理、红外传感器应用等关键知识点均有详细解析,并给出主程序、循迹模块、避障模块的设计思路,适合作为毕设写作参考或课设实操蓝本。

1. 循迹避障小车为什么非从 STC89C52+L298N 这套组合入手

第一次把 STC89C52 和 L298N 接在一起的小车通常会遇到“车能上电,但电机就是不转”,原因往往不是芯片坏了,而是共地没接、使能端悬空,或逻辑电源档位选错。这套标题所代表的毕设/课设方案,本质是把一辆小车拆成四个可独立验证的模块:STC89C52 负责逻辑决策,L298N 负责驱动直流减速电机,红外对管负责循迹,HC-SR04 负责避障。它不是性能最优的架构,却是把“传感器采集 → 单片机判断 → 功率输出”这条链路暴露得最清晰的组合,适合正在做课设、毕设的同学,也适合刚接手 51 项目的工程师把驱动和感知的基本功补齐。接下来的内容按接线、循迹、避障、验证的顺序推进,先把 L298N 的供电和 PWM 说透。

2. L298N 电机驱动模块:用 STC89C52 的定时器模拟 PWM 驱动直流电机

L298N 是双 H 桥驱动器,内部是两个 H 桥电路分别控制左右两路电机。之所以在 STC89C52 方案里反复出现,是因为它的供电逻辑简单:VS 接电机电源,VSS 接 5V 逻辑电源,GND 与单片机共地之后,就能用普通 IO 口直接控制正反转。STC89C52 的 IO 输出电流不足以驱动电机,L298N 在这里起的是功率放大和方向隔离的作用。

2.1 双 H 桥的供电分配与 STC89C52 的 IO 电流限制

L298N 模块板上通常有两路电源标注:一路是电机电源(丝印常见为 VMS 或 +12V),另一路是逻辑电源(VSS 或 +5V)。电机电源接电池正极,电压范围常见 6V 到 12V;逻辑电源 VSS 接稳定的 5V。STC89C52 的工作电压是 5V,所以 VSS 可以直接从同一组 5V 稳压输出取电。这里的第一个关键是共地:电池的 GND、L298N 的 GND、STC89C52 的 GND 三者必须接在一起,否则 IO 口的高电平没有参考基准,表现为电机忽转忽停或者完全不动。

第二个关键是电流分工。STC89C52 的准双向 IO 口在输出高电平时驱动能力很弱,灌电流虽然可以到 20mA 左右,但拉电流通常只有几百微安到几毫安,根本推不动直流电机这种感性负载。L298N 的作用是把单片机的小信号放大成电机需要的电流,IN1~IN4 只消耗微安级的逻辑电流。所以不需要在中间加三极管或光耦,IO 口到 L298N 输入引脚之间可以直接连线,更不需要加限流电阻。

2.2 最小接线表:电源、逻辑输入与使能端的接法

L298N 模块、STC89C52 和直流减速电机的接线,我一般这样接:

L298N 引脚STC89C52 / 电源说明
VMS(电机电源)电池 7.4V 或 9V 正极给电机和 H 桥功率部分供电
VSS(逻辑电源)5V 稳压输出STC89C52 也用同一路 5V
GND电池负极、单片机 GND三处共地
IN1P1.0左电机方向 A
IN2P1.1左电机方向 B
IN3P1.2右电机方向 A
IN4P1.3右电机方向 B
ENAP1.4 或接 5V左电机使能,接 PWM 可调速
ENBP1.5 或接 5V右电机使能,接 PWM 可调速
OUT1/OUT2左电机两根线正反接决定正转反转
OUT3/OUT4右电机两根线同上

IO 口的选择有讲究。P0 口在 STC89C52 上是开漏结构,不加外部上拉电阻时高电平不稳定,所以驱动电路不要放在 P0。P3 口上还有 RXD/TXD 和外部中断,留出来给超声波模块和串口调试更合适。P1 口作为 DIP-40 封装的准双向 IO,上电默认是高电平,直接接 L298N 的逻辑输入正好符合模块“高电平使能”的习惯。

2.3 用定时器 1 在 STC89C52 上模拟 PWM 调速

STC89C52 没有硬件 PWM 外设,常见的做法是用定时器中断模拟。我一般让定时器 1 工作在 8 位自动重装模式,周期固定 100 个计数,占空比则由一个全局变量pwm_duty_left控制。下面这段代码驱动左电机,右电机同理:

#include <reg52.h> // L298N 控制引脚 sbit IN1 = P1^0; sbit IN2 = P1^1; sbit ENA = P1^4; unsigned char pwm_duty_left = 60; // 占空比 60% unsigned char pwm_cnt = 0; void timer1_init(void) { TMOD &= 0x0F; // 只清 Timer1 的位,保留 Timer0 设置 TMOD |= 0x20; // Timer1 模式 2,8 位自动重装 TH1 = 256 - 100; // 周期 100 个计数 TL1 = 256 - 100; ET1 = 1; // 开 Timer1 中断 TR1 = 1; // 启动 Timer1 } void timer1_isr(void) interrupt 3 { pwm_cnt++; if (pwm_cnt < pwm_duty_left) ENA = 1; else ENA = 0; if (pwm_cnt >= 100) pwm_cnt = 0; } void motor_left_forward(void) { IN1 = 1; IN2 = 0; }

TMOD &= 0x0F保留低四位是为了不影响后面 HC-SR04 用到的 Timer0 配置。TH1 = 256 - 100把溢出周期设为 100 个机器周期,12MHz 晶振下每 100us 进入一次中断,PWM 基频约 100Hz,对减速电机足够平滑。pwm_duty_left的取值范围是 0 到 100,60 表示 60% 占空比。改这个全局变量就能在线调速。

需要提醒的是,中断里只改 ENA,不要动 IN1/IN2。方向引脚电平变化太快会在电机换向瞬间产生大电流尖峰,容易把模块上的续流二极管烧掉。先停车再换向是常规操作。

2.4 上电不转、单侧无力:L298N 最常见的 3 个坑

第一个坑是使能端悬空。L298N 模块默认带有跳线帽,如果拔掉了跳线帽又没有接任何电平,ENA/ENB 悬空,输出就是高阻态,电机自然不转。检查时先看跳线帽是否扣紧,或者把 ENA/ENB 直接接 5V。

第二个坑是电机电源电压过低。很多课设电池标称 7.4V,但镍氢电池在低压报警时实际掉到 6V 以下,L298N 内部 H 桥的饱和压降会吃掉 1.5V 到 2V,到电机端可能只剩 4V 多,车表现为单侧能转、负重就停。用万用表量 OUT1 和 OUT2 之间的电压,空载时接近 VMS 就正常。

第三个坑是 PWM 基频过高。有些同学把 TH1 装得很小,中断频率跑到 5kHz 以上,电机电感在高速斩波下发热,电流波形变差,转速反而下降。减速电机常见做法是 100Hz 到 500Hz,太低会听到明显的“哒哒”声,太高反而无力。

3. 循迹传感器布局与阈值判定:TCRT5000 数字量模块怎么接 STC89C52

循迹的本质是检测黑线和白色地面的反射差异。黑色吸收红外光,白色反射红外光,所以传感器读出的电压会明显不同。常见做法是买带 LM393 比较器的 TCRT5000 模块,输出是 TTL 电平,直接接 STC89C52 的 GPIO,不需要自己搭放大电路。

3.1 为什么选 TCRT5000 而不是光敏电阻

光敏电阻对环境光太敏感,室内灯光一变,阈值就要重新调。TCRT5000 是红外发射管加光电晶体管的组合模块,自带固定波长红外光,配合 LM393 比较器可以把模拟量在模块内部就变成 0/1。STC89C52 的 ADC 是额外扩展的,用数字量模块可以省掉 ADC 采样代码,直接在 GPIO 上读电平,课程设计最常见的做法。

模块上的电位器调节比较器参考电压。顺时针拧到底,灵敏度变高(更容易把浅色误判成黑线);逆时针拧到底,灵敏度变低(黑线可能读不出来)。调节目标是在黑白分界处刚好翻转。

3.2 三路循迹的安装位置与逻辑判定表

三路是性价比最高的组合。三个 TCRT5000 模块横向排开,间距 2cm 左右,安装在车头前方 1cm 到 2cm 处,离地高度 1cm 到 2cm。中间一个对准黑线中心,左右两个稍微超出线宽。安装后要保证三个传感器镜头在同一个水平面,否则弯道时两边的检测距离不一致。

模块输出低电平表示检测到黑线,高电平表示在白底上。三个信号的全部组合和对应动作:

S1(左)S2(中)S3(右)含义动作
111全白,可能冲出赛道直行,车身回正
110线在右侧边缘右转
101线在正中直行
100线偏右右转
011线偏左左转
010线在左侧边缘左转
001交叉路口或脱线继续直行
000全黑停车或恢复直行

这个表的前提是模块输出低电平为黑,不同模块可能相反,接好后先打印判断一次再写逻辑。

3.3 数字量输出模块的阈值调整步骤

调阈值不需要写代码,拿一个小螺丝刀在空地上操作就行。步骤是:把车放在纯白色地面,用螺丝刀调电位器,直到指示灯刚好熄灭;再把传感器放到黑线上,指示灯应该刚好亮起。两边余量合适的话,黑白两种状态下电压差至少在 1.5V 以上,这样运行中受环境光干扰也不会频繁翻转。

我一般会在调整后把模块对着光线变化比较大的窗口再试一次。如果指示灯在黑色和白色间抖动,说明模块离地太高,或者电位器调得太临界。常规做法是把离地高度降到 1cm 左右,重新调。

3.4 GPIO 读取与连续确认消抖代码

直接在 while 循环里读 IO 电平会受抖动和地面灰度影响。简单可靠的思路是连续采样 5 次,5 次结果一致才认为状态稳定:

#include <reg52.h> sbit S1 = P2^0; // 左 sbit S2 = P2^1; // 中 sbit S3 = P2^2; // 右 unsigned char read_track_state(void) { unsigned char i, sample, result = 0; for (i = 0; i < 5; i++) { sample = 0; if (S1 == 1) sample |= 0x01; if (S2 == 1) sample |= 0x02; if (S3 == 1) sample |= 0x04; result = sample; // 只保留最后一次采样 // 实际项目可以在这里统计高电平次数 } return result; }

这段代码的要点是:STC89C52 的准双向口作为输入前,要先向端口写 1,否则读到的全是被内部场效应管拉低的电平。result的 bit0、bit1、bit2 分别对应左、中、右传感器,返回值和上一节的判定表逐位对照。采样间隔里插入 1ms 左右延时,等红外发射管和比较器响应稳定后再读下一次,能滤掉大部分地面毛刺。

如果想更稳,可以改成计数器方式:每个传感器统计 5 次采样中高电平出现次数,大于等于 4 次才判为高,这样对黑白交界处的临界抖动有更强的容忍度。课设赛道上用简化版已经足够,关键是不要在一次采样后就改变转向,否则跨界线上的一瞬间会把车拐反。

3.5 环境光干扰与地面反光的缓冲处理

放在瓷砖地面做循迹时,可能遇到传感器在暗色瓷砖上误判成黑线。原因是瓷砖花纹对红外反射率分布不均。常见做法是让传感器离地更近,缩小检测范围,同时把比较器电位器调到“黑线亮、白地灭”的中间偏临界位置。如果教室灯光是荧光灯管,红外模块本身滤除了可见光干扰,但仍然要留意阳光直射的那几秒钟,强红外会在白地上把输出拉到黑线电平。我在课设里遇到这种情况,会直接给模块镜头加一段黑色热缩管,只留出正下方 5mm 的检测窗口,效果立竿见影。

4. HC-SR04 超声波避障:定时器 0 测距与循迹避障的状态切换

避障和循迹侧重点不同:循迹保证车跟着黑线走,避障保证黑线上突然出现障碍物时车不停下来。HC-SR04 量程在 2cm 到 400cm,用在桌面小车场景足够。

4.1 HC-SR04 的测距时序与 STC89C52 定时器选择

HC-SR04 工作流程:单片机的 Trig 引脚输出一个 10us 以上的高电平触发信号,模块内部发 8 个 40kHz 超声波脉冲,然后 Echo 引脚输出一个高电平,高电平持续时间就是声波往返时间。距离等于高电平时间乘以声速 340m/s 再除以 2。

Echo 高电平最长可达 20ms 左右,对应约 3.4m 量程。如果用延时函数死等 Echo 拉低,整个单片机都会被占住,循迹就没法做了。常见做法是用外部中断或者定时器 0 测量高电平脉宽。STC89C52 的 Timer0 是 16 位计数器,12MHz 晶振下最大计时 65.5ms,覆盖 HC-SR04 的量程没问题。

4.2 查询方式测距代码:TR0 启停与距离换算

#include <reg52.h> sbit TRIG = P3^4; sbit ECHO = P3^5; void delay_10us(unsigned char n) { while (n--); } unsigned int get_distance_cm(void) { unsigned int t; TRIG = 1; delay_10us(2); // 20us,大于规格书要求的10us TRIG = 0; while (ECHO == 0); // 等待Echo变高 TH0 = 0; TL0 = 0; TR0 = 1; // 开始计时 while (ECHO == 1); // 等待Echo变低 TR0 = 0; // 停止计时 t = (TH0 << 8) | TL0; return t / 58; // 单位cm }

t / 58是常用的工程近似:12MHz 晶振下 Timer0 每 1us 计一个数,声速往返换算后每个计数值约 0.017cm,所以 t 除以 58 得到厘米。更精确的写法是t * 17 / 1000,但取整除法在 C51 里开销大一些,精度要求不高时用 58 就够了。

这段代码有一个隐患:如果超声波模块没接好或障碍物太远,ECHO 可能一直为高,程序会卡死在while (ECHO == 1)里。实际课设里我一般给等待加超时保护,检测到溢出中断就退出。做法是在主循环里开个标志位,Timer0 溢出中断里置 1,主程序每过一个周期清一次。

4.3 循迹和避障的状态机:先停车再转向

这里给出一段状态跳转核心逻辑:

#define MODE_TRACK 0 #define MODE_STOP 1 #define MODE_AVOID 2 void main_loop(void) { static unsigned char mode = MODE_TRACK; // 默认循迹 if (mode == MODE_TRACK) { if (get_distance_cm() < 20) mode = MODE_STOP; // 进入停车判断 else track_follow(); // 执行循迹动作 } else if (mode == MODE_STOP) { motor_stop(); if (get_distance_cm() < 20) mode = MODE_AVOID; // 确认前方还有障碍 } else if (mode == MODE_AVOID) { if (turn_around_obstacle()) // 绕过障碍后回到线 mode = MODE_TRACK; } }

状态机的核心思想是避障优先级高于循迹。第一次测到障碍小于 20cm 时先停车,再测一次做到确认。如果连续两次都在 20cm 以内,说明不是偶然抖动,才进入避障动作。避障动作本身是一个完整的小车操纵序列:后退一点、向左或向右转 90 度、直行越过障碍侧面、再转回来。判断转向方向的常见做法是看哪一侧传感器的读数更大,障碍物离左边缘更近就向右转。这个判断不需要角度信息,只靠超声波的左右距离差就可以。

需要强调:get_distance_cm()里面有死等循环,一次测距最长可能占用 20ms,在这个时间段内车轮不会响应新的决策。所以状态机轮询周期不要设计得太短,20ms 级别的控制周期对这个小车来说已经够用。

4.4 Echo 引脚电平翻转的检查方法

如果小车在避障模式下频繁误转,先用万用表量 Echo 引脚空闲电平是不是低。HC-SR04 模块上电后,如果 Trig 悬空或初始化顺序错,Echo 可能一直保持高电平。常见做法是加一个上电复位流程:先给 Trig 一个低电平,延时 100ms,再进入主循环。这样保证模块完成内部初始化后才开始第一次测距。另外,超声波测距本身有 15 度左右的波束角,桌腿这类细长障碍物反射能量弱,读数会跳变,实际课设里两三次测距取最小值,比取平均值更接近真实障碍距离。

5. 小车验收进阶:用串口打印参数标定 PWM 占空比和避障阈值

5.1 用串口助手把障碍距离和 PWM 值打印出来

STC89C52 的串口 1 可以直接接 USB-TTL 模块,波特率设置在 9600 或 4800。初始化代码:

void uart_init(void) { SCON = 0x50; // 模式1,8位UART,允许接收 TMOD &= 0x0F; // 保留Timer1设置 TMOD |= 0x20; // Timer1模式2 TH1 = 0xFD; // 12MHz晶振,9600波特率 TL1 = 0xFD; TR1 = 1; }

打印格式建议用dist=30cm pwm=60% dir=left\n这样的文本,一行一条记录。观测时让车在黑线上匀速跑上一段,看距离数据和 PWM 输出是否符合预期。串口是验证传感器和驱动是否正常的捷径:L298N 不转,但串口能收到转向指令,问题就在驱动板;串口收不到距离变化,问题就在超声波或接线。用串口把调试信息分离出来,比直接改小车代码快得多。

5.2 用增量 PID 修正左右轮速差:先调 P 再调 I

硬件差异导致左右轮实际转速不同,车会走弧线。增量 PID 代码:

int error = target_speed - current_speed; int increment = kp * (error - last_error) + ki * error; pwm_duty += increment; last_error = error;

参数设置建议:kp 从 0.1 开始,车出现震荡就把 kp 减半。I 项在 P 项稳定后再加入,数值从 0.01 起调,避免积分饱和导致转向过头。

5.3 整车验收清单:黑线、障碍物、电池电量三个变量

  1. 空场地直线测试:左右轮同时给 60% PWM,看车是否走直。
  2. 循迹测试:在 1m 长的黑线上跑 5 次,观察是否脱线。
  3. 避障测试:在线上放一个高度 10cm 以上的障碍物,看小车能否在 30cm 以外完成停车和绕行。
  4. 低压测试:在 6.5V 低压下跑一遍,确认电机仍有输出、超声波模块仍能正常工作。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询