I²C EEPROM
14.1 概述
在上一节中,我们看到 I²C 协议让我们可以拥有能够轻松与 Z80 CPU 接口的组件,同时在板上占用非常小的空间。一种非常流行的组件是电可擦除可编程只读存储器,也称为 EEPROM。
从几个字节到 256KB 不等,它们让我们拥有非易失性存储器,可用于保存小型数据,同时只需要很少的信号线:SCL、SDA 和电源。
14.2 硬件实现
在 Zeal 8-bit Computer 上,我们已经有一个非易失性存储器:NOR Flash。尽管它可以在电路内直接从 Z80 重新编程,但其对我们的主要用途是作为 ROM 存储器,包含引导加载程序、操作系统或两者。事实上,在我们的情况中,它并不打算用于存储数据,因为有一个限制:页大小。为什么?因为在内部,NOR Flash 使用 4KB 页,这意味着要写入单个字节,我们需要擦除整个 4KB 页并重新写入。当然,这需要将页临时保存在 RAM 中以防止数据丢失。不太方便。
这就是为什么 Zeal 8-bit Computer 还嵌入了一个辅助非易失性存储器:一个 EEPROM。主板可以配备 32KB 的 24LC256 或 64KB 的 AT24C512。两种情况下,它们都安装在 DIP-8 插座中,在 PCB 上标记为 U14。
此外,它们的引脚排列相同,因此在本文的其余部分,我们将考虑后者,即 AT24C512。其引脚排列如下:
信号说明如下:
- $A_0$ 到 $A_2$:指定 7 位设备地址的低三位。高四位是
1010。在 Zeal 8-bit Computer 的情况下,这些引脚直接连接到 GND,因此 7 位设备地址为0x50。请注意,$A_2$ 在 AT24C512 的数据手册中被标记为 $NC$(未连接),但在 24LC256 中不是。在这两种情况下,这对我们的地址没有影响。 - $V_{cc}$ 和 $Gnd$:主电源(5V)
- $WP$:写保护引脚。在我们的情况中,它连接到 $Gnd$,因此 EEPROM 从不处于写保护模式
- $SCL$ 和 $SDA$:分别为 I²C 时钟和数据信号,更多信息请查看内部集成电路(I²C)章节
14.3 与 EEPROM 通信
写入 EEPROM
要向 EEPROM 写入数据,需要使用以下参数执行 I²C 写入事务:
- 设备地址为
0x50 - 2 个字节用于要写入字节的地址,MSB 优先
- 从上述指定地址开始写入 $n$ 个字节
向 EEPROM 发送写入命令后,它将开始处理该命令并在内部执行实际写入。在此过程中,它将停止响应任何其他 I²C 请求。换句话说,写入后,了解 EEPROM 是否再次准备好接受新请求的一种方法是使用虚拟读取命令轮询它,直到它成功回复。
例如,假设主设备想要将字节 0x45 和 0xaf 写入地址 0x2d10,请求将如下所示:
限制
我们可以注意到,可以在单个事务中写入多个字节。但是,请记住 EEPROM 也是分页的,因此不能写入跨越页边界的数据。
例如,AT24C512 具有 128 字节的页,第一页从 0x0000 开始,第二页从 0x0080 开始,第三页从 0x0100 开始,依此类推。
因此,可以从 0x0000 开始执行 128 字节的写入,但不能从 0x0075 开始执行 16 字节的写入,因为最后一个字节的地址理论上是 0x0085,这是一个与起始页不同的页。
实际上,在后一种情况下,EEPROM 会接受写入,但它会回绕当前写入地址,因此最终会将所有剩余字节写入页的开头,而不是"跳转"到下一页。
此限制在官方数据手册中有记录。
从 EEPROM 读取
要执行 EEPROM 读取,有两种模式可用:当前地址模式和随机读取模式。
当前地址模式在执行 I²C 读取操作时使用。为了确定要读取字节的地址,EEPROM 维护一个存储当前地址的内部 16 位缓冲区。在此模式下,每次读取一个字节时,该地址都会递增。
随机读取模式在执行 I²C 写-读操作时使用。为了确定要读取字节的地址,主设备必须首先发送(写入)该地址,然后立即开始读取操作,而不发出 STOP 条件。与写入模式类似,16 位地址必须MSB优先发送。 此模式会改变内部当前地址缓冲区,因此也可用于设置其值。
两种模式都支持顺序读取,允许主设备检索第 1、第 2、第 3、……、第 $n$ 个字节,直到发出 STOP 为止。
例如,假设主设备想要从地址 0x2d10 开始读取 $n$ 个字节,可以使用以下写-读操作:
注意
需要注意的是,在当前地址读取模式下,数据手册没有说明上电时的初始值是什么,因此,至少在使用随机读取模式一次之后,再使用该模式会更安全。
14.4 扩展更多 EEPROM
得益于 $A_0$、$A_1$ 和 $A_2$ 引脚,可以连接最多 8 个类似的 EEPROM,这些 EEPROM 的设备地址高四位为 1010。
因此,我们可以设想一个连接到用户端口的扩展板,上面有三个 AT24C512 EEPROM,使得可用的非易失性 I²C 存储器总量达到 256KB。
这些设备的 $A_1$ 和 $A_0$ 引脚需要分别按如下方式连接:
- GND,5V(0,1)
- 5V,GND(1,0)
- 5V,5V(1,1)
这样,它们各自的设备地址分别为 0x51、0x52 和 0x53。