搭建路径中级一个周末

用 8051 单片机做一台循迹机器人

一台在裸 8051 上运行的循迹车——并且清楚理解 Arduino 本来会替你隐藏起来的每一层,从复位电路到 PWM 波形。

用 8051 单片机做一台循迹机器人 技术示意图SENSOR ERROR

几乎每一门教单片机的工程课程,最后的作业都是同一个:在 8051 上做一台循迹车。它之所以是个好作业,原因通常没人说——这颗芯片什么都不给你。没有 analogWrite() 让你设定电机转速,没有 analogRead() 读传感器,也没有驱动板用的库。你平时习惯调用的每一层,都要自己建起来。

这就是这条制作路线和 Arduino 循迹车之间的区别。机器人是同一台,深度却不是。你要亲手写出 Arduino 在硅片里已经做好的脉宽调制(PWM)生成器,弄明白为什么 8051 的引脚只有反接才能点亮 LED,并且在买任何东西之前就确切知道,你的电机控制究竟吃掉了多少 CPU。

8051 是一颗 40 脚封装的 8 位 Harvard 架构单片机,通常是带 8 KB 闪存和 256 字节 RAM 的 AT89S52。它没有 PWM 外设,端口是准双向的(读输入之前必须先写 1),引脚吸收的电流比提供的多——所以 LED 要接在吸收端,而电机驱动的 H 桥(高边桥)需要上拉才能被可靠驱动。这些细节听起来像脚注,直到机器人完全不动了,你才发现原因是 EA 悬空,或者复位是高电平有效而你把它接到了低电平。

你从面包板起步,只有芯片、一枚 11.0592 MHz 晶振和两个负载电容、一套复位网络,以及把 EA 拉高——这是真正能执行代码的最小电路。前三篇教程会带你走遍架构与内存映射、通用输入输出(GPIO)与端口对外接口,然后用定时器 0 的 8 位自动重装模式手搓出 PWM:大约 460.8 Hz、5% 的步进,占用大约四分之一的 CPU——这是你没有外设所必须付出的代价。

从这一步开始,路线就和 Arduino 循迹车汇合了:同样把红外(infrared)反射阵列压缩成一个加权误差,同样的 PID(比例-积分-微分)转向,以及同样在浏览器模拟器里找出能干净过弯的增益。技术树把硬件节点和概念节点分开,所以前半程只需要芯片和一支 ISP(在系统编程)烧录器(比如 USBasp),只有最后两个制作节点才需要底盘、电机和传感器阵列。

技术树按序走。前三节点面包板芯片就行,循迹增益浏览器模拟器调,后两步底盘电机要。进度这台设备存。

物料单

零件 数量 约价 说明
AT89S52 40 脚 DIP 1 $2 **在系统可编程。**AT89C51 要手里没有的并行烧录器
USBasp ISP 烧录器 1 $3 AT89S52 经 SPI 烧——实用就靠它
11.0592 MHz 晶振 1 $0.50 **不要用 12 MHz。**见下文——这不是偏好问题
33 pF 瓷片电容 2 $0.20 晶振负载电容
10 µF 电解 + 10 kΩ 电阻 各 1 $0.20 复位网络。这里复位高有效
10 kΩ 排阻 1 $0.50 P0 上拉——开漏无它高出不来
40 脚 ZIF/DIP 座 1 $1 芯片绝不直焊;拔它
红外反射阵列 1 $5–10 数字输出,或外 ADC——8051 无模拟输入
L298N 1 $3
TT 减速电机 2 $4
两轮底盘 1 $6–10
电池包 1 $6
面包板杜邦线 — $5 前三里程碑全这发生

合计约 $35–50。

有两件买什么,会决定这个项目是做得开心还是做得痛苦。

**晶振必须是 11.0592 MHz。**8051 是靠定时器 1 溢出来产生串口波特率的,而在 11.0592 MHz 下,每一个标准波特率算出来的重装值都是整数——9600 波特率正好对应 TH1 = 0xFD。用 12 MHz 晶振,对应目标是 9600 却会算出 10417,也就是 8.5% 的误差,远超 UART 大约 3% 的容忍度。于是每一个字符到达时都是坏的。芯片在你想打印点什么来调试之前一切正常,而那恰恰是最糟糕的发现时机。

传感器阵列必须是数字输出,否则你必须外加一颗 ADC,比如 ADS7828 或 ADC0808。8051 完全没有模拟输入。这是这颗芯片从你手里拿走、而 Arduino 白送给你的第一样东西,值得有意识地做取舍:比较器输出更简单,但你会失去那个平滑的比例误差信号,而它正是让 PID 调得好的关键。

最小电路

传感器电机前,面包板光芯片跑代码先。六连接:

引脚 接到 为什么
40(VCC) +5 V
20(GND) 地
31(EA) +5 V 选内部程序存储器。悬空接地芯片从不存在的外部存储器取纹丝不动
18、19(XTAL2、XTAL1) 晶振两端 每腿对地 33 pF 电容
9(RST) +5 V 经 10 µF,对地 10 kΩ 这里复位高有效——几乎别的单片机反过来

EA 悬空是第一块 8051 板子看起来像坏了的头号原因,而且它不产生任何报错、任何指示灯、任何线索。每次都先查它。

在 P1.0 上接一颗 LED 就是这个项目的“hello world”:负极接引脚,正极经一个 330 Ω 电阻接到 +5 V,写 0 点亮。引脚能吸收约 10 mA,却只能提供大约 60 微安,所以反过来接的话它只会发出微弱的光,看起来像是故障。

里程碑制作

前三面包板芯片就行,底盘买前走老远。

# 里程碑 测试 通过长这样
1 芯片跑 P1.0 LED 闪 闪。不闪先查 EA 别的后
2 时序已验证 用计数延迟精确地以 1 Hz 闪烁 秒表测 60 次闪烁,误差在一秒以内
3 串口正常 以 9600 波特率打印一个计数器 文本干净——出现乱码就是晶振不对
4 GPIO 进 P1.1 按键上拉读 可靠读。读前写 1 记住
5 定时器中断 Timer 0 ISR 翻脚,示波器计时 周期算的稳
6 软件 PWM 以 0%、25%、50%、100% 占空比驱动一颗 LED 亮度明显不同,且没有闪烁
7 PWM 开销量出来了 在主循环里翻转一个备用引脚并计时 你能说出这个中断服务程序占用了多少比例的 CPU
8 电机驱动 两轮指令占空比正反 正反速度,台架
9 传感器读 线地面全通道打印 每通道两分得出
10 误差信号 用手推着机器人横穿黑线 加权位置单调变化,没有跳变
11 跟随 胶带椭圆跑 整圈完

里程碑 7 正是这个项目存在的理由。Arduino 的 analogWrite 不花任何代价——PWM 是在硅片里生成的。而这里你是用一个定时器中断手搭出来的,它每秒要触发几万次。把它占用了多少比例的 CPU 量出来,就是这一课的要义:通常是整颗芯片的四分之一,而这正是硬件 PWM 外设帮你省下的东西。

做好长什么样

测量 这台典型
11.0592 MHz 机器周期 1.085 µs——指令数时序知道
软件 PWM 频率 Timer 0 八位自动重装约 460 Hz 5% 步
PWM ISR 吃 CPU 约 25%
主循环剩余的频率 控制环仍有充裕的 200 Hz 以上
RAM 占用 256 字节中不到 100 字节——这个约束真实存在,但在这里并不紧张
跟随性能 与 Arduino 版本相当;这台车本身不是重点

最后这一点值得直说:**这台机器人不会比 Arduino 循迹车更强。**它是同一台机器人,只是用更费力的方式造出来,而它的回报是理解而不是性能。如果你想做一台更好的循迹车,去调 Arduino 那台。如果你想知道 analogWrite 一直在替你做些什么,那就来造这台。

故障排查

现象 可能原因 解决
芯片彻底没反应 EA 悬空接地 31 脚接 +5 V
还是没反应 EA 高 晶振没起振 33 pF 电容晶振焊点查
不停复位 RST 拉高 高有效——10 µF / 10 kΩ 网络查
串口打印乱码 12 MHz 晶振 11.0592 MHz,或接受无串口调试
LED 很暗 拉电流接 负极接脚;写 0 点亮
P0 读写全无 开漏无上拉 每脚 10 kΩ 到 +5 V
PWM 周期抖 ISR 重装晚 第一句重装或模式 2
程序回到随机地址 堆栈压寄存器组 1 main() 顶 SP = 0x30;
代码一多行为就诡异 RAM 用光了 总共只有 256 字节——查链接器生成的 map 文件
烧录器认不出芯片 ISP 脚占用或复位失控 烧录时 P1.5–P1.7 RST 释放
传感器无用值 无 ADC 芯片上模拟阵列 数字输出阵列或外 ADC

下一步去哪

**再加一个定时器,量一量你自己的主循环。**定时器 0 跑着 PWM,定时器 1 就可以用来数控制循环的周期,把“感觉跟手”变成一个数字。在一颗你能数机器周期的芯片上,这个数字是完全可以精确预测的——去验证你的预测。

通过端口 0 接一块 LCD,你就会正面碰上开漏这个问题,外加一个确实比处理器慢得多的设备所带来的时序要求。

然后去做 Arduino 版本——并留意你现在对其中每一行的理解。那一行 analogWrite,在这里就是你要花一个晚上写的那个中断服务程序;那个 analogRead,就是你不得不外加的 ADC。这番对比才是这个项目真正的交付物。

项目路线图

搭建路径

沿着技术树,从零件一路走到一台能正常工作的机器人。每个节点在其前置条件完成后解锁,你的进度会保存在这台设备上。

已完成 0 / 17

100%
搭建

给机器人接线

60 分钟

搭建

烧录并运行

60 分钟

目标

8051 循迹车完成

你做出来了

元器件

本路径中的教程

接线之前先练习

用在线模拟器把它调好

搭建路径会经过一个浏览器实验台。先在这里把行为调对,再把参数迁移到真实的机器人上。

常见问题解答

为什么要在 8051 而不是 Arduino 上做循迹车?

因为 8051 逼着你亲手搭建 Arduino 替你隐藏起来的东西。没有 analogWrite,所以你要自己写 PWM 生成器;没有 pinMode,所以你会弄明白准双向端口究竟是怎么工作的。如果目标是做一台能用的机器人,就用 Arduino。如果目标是理解这台机器人,8051 每小时教给你的东西,比任何一块什么功能都有现成库的开发板都多。

做一台 8051 循迹车需要哪些零件?

一颗 AT89S52 及其晶振和复位电路、一个红外反射传感器阵列、一个 H 桥驱动器(比如 L298N 或 L293D)、两个 TT 减速电机、一个两轮驱动底盘,以及一个能让逻辑供电和电机供电走不同电源轨的电池包。你还需要一个 ISP 烧录器——USBasp 非常便宜,只通过四个引脚就能给 AT89S52 烧录程序。

8051 没有 PWM 硬件,怎么控制电机转速?

用软件生成 PWM。定时器 0 工作在 8 位自动重装模式,每 100 个机器周期中断一次;中断程序对节拍计数,并在每个周期的前 N 个节拍里保持输出为高电平。在 11.0592 MHz 下,这能得到 460.8 Hz 的频率和 5% 的占空比步进,代价是大约四分之一的 CPU——这就是没有 PWM 外设所要付出的代价。

代码可以用 C 写吗,还是必须用汇编?

用 C 完全没问题,这也是现在大多数课程采用的方式。Keil C51 是业界标准,SDCC 是免费的开源替代品。在这颗芯片上,汇编值得读一读——指令集很小,时序也可以逐条计数——但你不必用它写出一整台机器人的程序。

为什么我的 8051 机器人烧录之后完全没反应?

先检查 EA(31 脚)有没有接到 +5 V,这一步要排在一切之前。如果它悬空或接地,芯片会试图从并不存在的外部存储器里取程序,于是什么也不运行,而且没有任何报错。然后再检查复位电路——8051 的复位是高电平有效——以及晶振的两个负载电容。

开始这个项目之前需要先买零件吗?

不需要。循迹逻辑和增益调整都可以在浏览器模拟器里完成,而三篇 8051 教程只需要把芯片插在面包板上。等你准备好给实体机器人接线时,再去买底盘和电机。