亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

面包板计算机程序员

组件和用品

Arduino UNO
× 1

关于这个项目

这是什么项目?

这是 Ben Eater 的 8 位面包板计算机项目的扩展。我非常喜欢观看 Ben 关于如何构建面包板计算机并构建我自己版本的视频。如果您还没有关注 Ben,那么我强烈建议您在阅读之前观看他的视频 - 如果没有上下文,这个项目将毫无意义。

组装完计算机后,很快就清楚了,如果我每次打开程序时都必须通过 DIP 开关手动切换程序,那么它根本看不到太多用处。即使一次又一次地切换仅 16 个字节也会很快变老。我还计划将内存扩展到 256 字节,这只有在可以加载和保存程序的情况下才有用。

我可以用它做什么?

  • 从面包板计算机 RAM 中保存程序
  • 将程序加载到面包板计算机的 RAM 中
  • 在面包板计算机启动时自动运行保存的程序
  • 通过串行连接检查和修改内存内容
  • 用汇编语言对面包板计算机进行编程
  • 反汇编内存内容
  • 单步说明
  • 设置断点并运行到断点

这是演示这些功能的视频。请原谅视频质量 - 我绝不是专业的视频内容创作者:

它是如何工作的?

在制作这个项目时,我有几个目标:

  • 构建它所需的硬件尽可能少
  • 尽可能少对面包板计算机本身进行更改

一开始我想使用 EEPROM 来存储程序,然后使用某种逻辑将程序从 EEPROM 传输到面包板计算机的 RAM。然而,事实证明,提出传输逻辑比我能处理的要复杂(尽管我真的很喜欢在硬件附近工作,但我更像是一个软件人)。我碰巧是 Arduino 的忠实粉丝,所以在某个时候我开始考虑用 Arduino 替换传输逻辑。花了一些时间说服自己使用 Arduino 并没有作弊(毕竟,即使是 Arduino UNO 也比面包板计算机本身强大得多)但我对结果很满意,所以我已经做到了。

那么Arduino需要能够做什么?那么,它需要能够从内存中读取数据并将数据写入内存。最简单和最少干扰(对面包板计算机)的方法是使用内存模块已有的相同接口:总线和控制信号。 Arduino 数字 I/O 引脚是双向的,因此将其中的 8 个直接连接到总线允许 Arduino 读取和写入总线。要使 RAM 模块从总线读取或写入总线,所需要做的就是相应地设置 MI/RI/RO 信号。现在这些信号通常由控制逻辑的 EEPROM 驱动,因此让 Arduino 控制它们也会导致冲突和可能的短路情况。然而,Ben 使用的 AT28C16 EEPROMS 具有芯片使能 (CE) 输入,可将所有数据输出置于高 z 状态 - 然后允许 Arduino 操纵信号。要读取 RAM,Arduino 需要执行以下操作:

  • 将 EEPROM 的 CE 信号设置为高电平(即禁用控制逻辑)
  • 将要读取的第一个地址输出到总线上
  • 将 MI 信号设置为高电平并等待时钟低-高转换
  • 将 MI 设置为低电平,将 RO 设置为高电平并等待时钟低-高转换
  • 从总线读取数据字节
  • 对所有 16 个地址重复第 2 步
  • 将 EEPROM 的 CE 信号设置为低电平(即重新启用控制逻辑)

就是这样。写入RAM内容非常相似,Arduino只需要写入总线并将RI设置为高而不是RO。当然还有一些技术问题需要解决,但上述基本机制是这个项目的核心。

我需要对面包板计算机进行哪些更改?

有两个更改需要进行:

  • 在控制逻辑 EEPROM 的数据输出端放置下拉电阻
  • 在禁用 EEPROM 时禁用(或持续重置)环形计数器

下拉电阻

下拉电阻是必需的,因为一旦 EEPROM 被禁用,控制信号(例如 AO/AI/EO...)所连接的逻辑门的上拉电阻会将这些信号拉高。这意味着多个寄存器将写入总线,从而导致冲突。

74LS 门输入端的上拉电阻在 10k 左右。因此,下拉电阻器需要足够小以将电压降低到低区域。对于大多数信号线,我使用了 3.3 kOhm 电阻器。但是,有两个例外:首先,“SU”信号连接到 8 个异或门,这意味着有效上拉电阻为 10kOhm/8 =1.25kOhm。下拉电阻必须明显小于 1k 才能拉低。幸运的是,SU(减法)信号不控制与总线的任何交互,因此我们可以忽略它并且没有下拉电阻。其次,CE(计数器使能)需要一个 1k 下拉电阻 - 在某些情况下,较大的值会导致随机程序计数器行为。

我发现在装有所有蓝色 LED 的面包板上添加下拉电阻最容易,即在 LED 阳极(连接到 EEPROM 输出)和 GND 之间。

[我无法在此处为 HLT/MI/RI 信号安装电阻,因此我在面包板上的其他位置添加了电阻]

环形计数器重置

另一个修改是重置环形计数器。从技术上讲,这对于允许保存/加载程序并不是真正必要的,但它允许将控制从 Arduino 顺利转移回控制逻辑。关键是只要 CE 为高(即禁用控制逻辑),就将环形计数器保持为 0。当 Arduino 将 CE 切换回低电平(启用控制逻辑)时,环形计数器将为零,面包板计算机开始执行下一条指令。

对于我的构建,我不需要为此做任何事情,因为我使用一个 EEPROM 输出来重置环形计数器。这通过在指令完成后立即重置环形计数器来提高性能。当控制逻辑 EEPROM 被禁用时,它还自动为我提供环形计数器重置:EEPROM 输出上的下拉电阻会将信号拉低,从而重置环形计数器。

如果您使用 Ben 的固定 5 步环形计数器的实现,我认为当 CE 为高时,他的重置电路的以下扩展应该重置计数器(单击下面的左/右箭头以在 Ben 的原始电路和扩展版):

如您所见,它需要另外 3 个与非门,即多一个 74LS00 芯片。请注意,我还没有测试过这种方法,但就我所见,它应该可以工作。

这种修改不是绝对必要的——你可以在一开始就省略它。加载和保存以及监视器/汇编器/反汇编器仍然可以正常工作。但是,任何需要将控制权从 Arduino 转移到控制逻辑的操作都将不起作用。最值得注意的是在启动时自动运行保存的程序以及在调试器中单步运行。

我如何设置 Arduino?

将 GIT 存档中的草图上传到 Arduino 并将 Arduino 连接到面包板计算机,如下所示:

  • Arduino 5V 引脚(不是 Vin!) 到面包板上的 5V 轨
  • Arduino GND 引脚到面包板上的 GND 引脚
  • Arduino 数字引脚 2-9 到总线 0-7
  • Arduino 数字引脚 10,用于控制控制 RO 的逻辑 EEPROM 输出
  • Arduino 数字引脚 11,用于控制控制 RI 的逻辑 EEPROM 输出
  • Arduino 数字引脚 12,用于控制控制 MI 的逻辑 EEPROM 输出
  • Arduino 模拟引脚 0 到时钟信号
  • Arduino 模拟引脚 3 到 all 的 CE(引脚 18) 控制逻辑 EEPROM 通过一个 10k 电阻到 +5v

除此之外,您需要将 Arduino 的模拟 1 和模拟 2 输入引脚连接到 DIP 开关和按钮,如原理图所示(有关更多详细信息,请参阅随附的 Fritzing 文件)。

对于绝对最小(但仍然有效)的版本,您可以执行以下操作:

  • 在控制 AO、CO、EO、IO、RO 的 EEPROM 输出引脚上添加 3.3kOhm 下拉电阻
  • 跳过上面的“环形计数器重置”说明
  • 如上图所示进行 Arduino 到面包板计算机的接线(如果需要,您可以在最后一步中省略 10k 电阻)
  • 将模拟引脚 1 和模拟引脚 2 连接到 GND

要使用加载/保存按钮,您只需根据原理图将按钮、DIP 开关和相关电阻连接到模拟引脚 1 和 2。

要使用自动启动功能,Arduino 需要在重置期间和程序传输期间将程序计数器保持在 0,并将环形计数器保持在 0。当 Arduino 复位时,模拟引脚 3 和 +5V 之间的上拉电阻保持控制逻辑禁用(因此程序计数器为 0)。对于环形计数器,请按照上面的“环形计数器重置”说明进行操作。

如何加载和保存程序?

上面的最小设置将允许您通过串行接口控制 Arduino。要与 Arduino 通信,您需要一个终端程序,例如 Putty 或 TeraTerm。 Arduino 软件中的串行监视器也可以工作,但串行监视器中输入和输出区域之间的分离使它在这种情况下有点笨拙。

  • 打开面包板计算机
  • 通过 USB 数据线将 PC 连接到 Arduino
  • 启动终端程序并配置为9600波特,8位,无奇偶校验,1个停止位
  • 在终端窗口中按 ESC 进入监控模式
  • 您应该看到一个“。”作为命令提示符
  • 输入“h”并按回车键以获取支持的命令列表

通过最少的设置,您应该能够使用“m”、“M”、“C”、“l”和“s”命令。这些允许您查看内存内容、修改内存内容以及加载和保存程序。

通过按钮保存或加载程序:

  • 关闭面包板计算机的时钟
  • 设置 DIP 开关以选择保存数据的文件编号。
  • 按“保存”或“加载”按钮。连接到 CE 的 LED 将亮起,表示 Arduino 已获得控制
  • 打开面包板计算机的时钟。您应该看到 Arduino 在地址之间循环(观察内存地址寄存器的 LED)
  • 等到总线 LED 停止闪烁且内存地址寄存器的 LED 停止闪烁并显示 1111
  • 关闭面包板计算机的时钟。 CE 连接的 LED 将熄灭,表示控制已返回控制逻辑

要在启动时自动运行程序(确保您拥有所有必要的电路),只需将 DIP 开关设置为保存程序的文件编号,然后打开面包板计算机(或按下重置按钮)。有两种特殊情况: 如果所有 DIP 开关都关闭,则计算机会定期启动,不会自动启动。如果所有 DIP 开关都打开,则 Arduino 在启动时直接进入监控模式。

如何使用汇编和反汇编?

要使用汇编器/反汇编器和调试器功能,您首先需要更改 Arduino 上的程序以符合您的特定设置。在源代码中找到定义 opcodes_4bit 结构的部分:

struct opcodes_struct opcodes_4bit [] ={{"NOP ", B00000000, 0, false}, {"LDA ", B00010000, 2, true}, ... {".OR ", B11111110, 0, true}, // 设置起始地址 {".BY ", B11111111, 0, true}, // 定义一字节数据 {NULL, 0, 0, false} }; 

每行指定一个操作码:

  • 第一个字段是助记符(“LDA”)。对于立即寻址,请在助记符中包含“#”。因此,Ben 所谓的“LDI”在这里将被称为“LDA #”。你能说我是在 C64 上编写 6510 汇编程序长大的吗?
  • 第二个字段是操作码本身。低四位应始终为 0。(特殊操作码 .OR 和 .BY 除外,见下文)
  • 第三个字段是操作码执行所需的周期数(这是除了获取周期之外的)。例如,在我的实现中,LDA 的操作码为 0001,总共需要四个周期来执行,其中两个是获取周期。如果您遵循 Ben 的说明(所有操作码都使用 5 个周期),那么这应该始终为 3。
  • Last 字段指定此操作码是否需要参数。例如,LDA 需要一个参数,而 OUT 不需要。

您需要调整此列表以反映您为面包板计算机实现的操作码。最后两行是汇编程序使用的特殊操作码,应保持原样。

输入所有操作码后,将软件上传到 Arduino。连接您的终端并进入监控模式(通过在终端窗口中按 ESC 或将所有 DIP 开关设置为打开)。您现在应该可以反汇编您的程序了。在监视器中只输入“d”将在地址 0 处开始反汇编。

汇编器很小,但工作得很好。键入“a”开始在地址 0 处组装。约定是:

  • 如果一行开始不是以空格开头,那么它必须以标签定义开头。标签必须以字母字符开头,后跟字母数字字符,长度最多为 3 个字符,并且区分大小写。
  • 在一行中的第一个空格之后,汇编器需要一个助记符(LDA、STA、OUT...)。
  • 特殊助记符“.BY”直接指定要存储在当前位置的数据字节。
  • 特殊助记符“.OR”告诉汇编器在新地址继续汇编。
  • 如果参数以字母字符开头,则假定它是一个标签。
  • 任何数字参数都应该是十进制数。要指定十六进制,请在参数前加上“$”。例如,要将十六进制 FF 数加载到 A 寄存器中,请使用“LDA #$FF”。
  • “;”之后的任何内容假定为注释并被忽略。

例如,斐波那契代码可以输入如下:

rst LDA #0; x =0 STA x LDA #1; y =1 STA y lp ADD x; z =y + x STA z JC rst;如果溢出 OUT 则重新启动;打印 z LDA y; x =y STA x LDA z; y =z STA y JMP lp;循环 x .BY 0 y .BY 0 z .BY 0  

有哪些限制?

为了节省 Arduino 上的 RAM 空间,汇编器作为 1-pass 汇编器工作(否则 Arduino 将不得不缓冲所有源代码)。汇编器在输入操作码时将它们写入面包板计算机的内存中。这意味着组装会被面包板计算机的时钟速度减慢。如果您将文本复制并粘贴到终端窗口中,这可能会导致字符丢失,因为 Arduino 无法跟上以 9600 波特输入的字符(因为它花费了太多时间等待面包板计算机的时钟)。要解决这个问题,要么降低波特率,要么使用 TeraTerm,它提供了一个设置来指定发送的字符之间的延迟。另一种解决方法是提高面包板计算机上的时钟速度。我的时钟频率高达 160kHz,在这个速度下,我可以毫无问题地以 9600 波特率复制和粘贴代码。

在其默认配置中,Arduino 草图可以处理面包板计算机上高达约 1-2kHz(可能更高)的时钟频率。请注意,默认配置下 Ben 的时钟不会超过 500Hz。如果您的时钟更快,请查找 #ifdef FAST_IO 在代码中切换。打开 FAST_IO 应该使 Arduino 以高达 250kHz 的时钟速度工作。我已经测试了它高达 160kHz。通过直接在汇编程序中实现时间关键循环,可能可以支持更高的速度,但老实说,160kHz 的时钟速度在面包板计算机上已经感觉太快了,否则功能有限。开启FAST_IO前请务必阅读代码中相应的注释。

Arduino 有 1k 的 EEPROM,因此可以容纳 1024/16=64 个不同的程序。实际上它是 63,因为保留了 16 个字节来保存配置数据。这不是很多,但可能足以容纳您可以提出的所有程序。只能通过 DIP 开关(1-14 用于自动启动)选择其中的 0-15 号程序,但“s”和“l”命令将适用于整个 0-62 范围。

看起来有点乱。你能把它整整齐齐吗?

是的!在我这里的最终版本中,我实际上只使用了裸 Atmega 328P 芯片(连同 16MHz 晶体和电容器)而不是 Arduino UNO。 UNO 上的电压调节器在这里不是必需的,因为 Arduino 无论如何都直接使用我们电源的 5V。唯一的损失是我们现在必须使用单独的 USB 到串行转换器(FTDI 或类似的)来与 Atmega 通信。它的整体外观更适合面包板计算机的其余部分:

另一个优化是从 Arduino/Atmega 中删除引导加载程序。这消除了 Arduino 引导加载程序启动时的 2 秒延迟。如果人们感兴趣,我将发布有关如何执行此操作的说明。在评论中告诉我!

代码

面包板计算机程序员
面包板计算机程序员的 Arduino 草图 https://github.com/dhansel/programmer

示意图

drive_pD8k28E85v.fzz

制造工艺

  1. 电脑鼠标
  2. 使用真实传感器控制效果
  3. Arduino Spybot
  4. FlickMote
  5. 自制电视 B-Gone
  6. 主时钟
  7. 找到我
  8. Arduino Power
  9. Tech-TicTacToe
  10. Arduino Quadruped
  11. ThingSpeak Arduino 气象站
  12. Arduino Joystick