引言
你是否曾想过存储那些断电后依然保留的数据?在嵌入式系统中,EEPROM(电可擦可编程只读存储器)是非易失性存储的首选。今天,我们将使用 Raspberry Pi Pico 模拟 I2C EEPROM 的读写操作——这一切都在你的浏览器中通过 Velxio 完成!无需任何硬件。
我们将向 EEPROM 写入几个字节,再读取回来,并验证它们是否匹配。在此过程中,你将学习 I2C 协议、Wire 库以及如何调试串口输出。让我们开始吧!
电路详解
在 Velxio 中打开示例,你会在画布上看到电路。主要组件包括:
- Raspberry Pi Pico(微控制器)
- 红色 LED(标记为
led-write)—— 写入操作时点亮 - 绿色 LED(标记为
led-read)—— 读取操作时点亮

接线详情
| 来自(Pico 引脚) | 连接到(组件) | 导线颜色 |
|---|---|---|
| D12 (GPIO12) | 红色 LED 阳极 | 红色 (#ff4444) |
| D10 (GPIO10) | 绿色 LED 阳极 | 绿色 (#00cc00) |
| 红色 LED 阴极 | GND.1 | 黑色 (#000000) |
| 绿色 LED 阴极 | GND.1 | 黑色 (#000000) |
注意: 在此模拟中,I2C EEPROM 是虚拟的——它内置于 Velxio 环境中。LED 用作视觉指示器:红色 LED 在写入时闪烁,绿色 LED 在读取时闪烁。在实际电路中,你需要将 EEPROM 的 SDA 和 SCL 线连接到 Pico 的 I2C 引脚(默认是 GPIO4 和 GPIO5,但这里我们使用 D12 和 D10 连接 LED)。
代码详解
让我们来分解这个 Arduino 代码。代码使用 Wire 库通过 I2C 进行通信。
包含头文件和定义
#include <Wire.h>
#define EEPROM_ADDR 0x50
我们包含 Wire 库,并将 EEPROM 的 I2C 地址定义为 0x50。这是 24LC 系列 EEPROM 的常见地址。
辅助函数
void eepromWrite(byte memAddr, byte data) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(memAddr);
Wire.write(data);
Wire.endTransmission();
delay(5); // EEPROM 写入周期
}
byte eepromRead(byte memAddr) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write(memAddr);
Wire.endTransmission();
Wire.requestFrom(EEPROM_ADDR, 1);
return Wire.available() ? Wire.read() : 0xFF;
}
eepromWrite:发送内存地址,后跟数据字节。delay(5)模拟 EEPROM 的内部写入周期(通常为 5 毫秒)。eepromRead:首先发送内存地址(一个“虚拟写入”),然后从 EEPROM 请求一个字节。返回该字节,如果没有可用数据则返回0xFF。
初始化
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin();
Serial.println("=== Pico I2C EEPROM 测试 ===");
Serial.println();
// 写入 8 个字节
Serial.println("正在写入 8 个字节...");
byte testData[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE};
for (int i = 0; i < 8; i++) {
eepromWrite(i, testData[i]);
Serial.print(" ["); Serial.print(i);
Serial.print("] = 0x");
if (testData[i] < 16) Serial.print('0');
Serial.println(testData[i], HEX);
}
Serial.println();
// 读取回来
Serial.println("正在读取...");
int pass = 0;
for (int i = 0; i < 8; i++) {
byte val = eepromRead(i);
Serial.print(" ["); Serial.print(i);
Serial.print("] = 0x");
if (val < 16) Serial.print('0');
Serial.print(val, HEX);
if (val == testData[i]) {
Serial.println(" 通过");
pass++;
} else {
Serial.print(" 失败 (期望 0x");
Serial.print(testData[i], HEX);
Serial.println(")");
}
}
Serial.println();
Serial.print("结果: ");
Serial.print(pass);
Serial.println("/8 通过");
}
- 以 115200 波特率初始化串口,并用
Wire.begin()初始化 I2C 总线。 - 将 8 个字节(
0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE)写入地址 0–7。 - 读取每个地址并与原始数据比较。打印“通过”或“失败”。
- 最后打印通过的测试数量。
主循环
void loop() {
delay(10000);
}
无需重复执行任何操作——测试在 setup() 中只运行一次。主循环仅用于延迟,以便串口输出保持可见。
关键概念
- I2C 协议:一种用于微控制器和外设之间通信的两线串行总线(SDA, SCL)。每个设备都有一个唯一地址。
- Wire 库:Arduino 内置的 I2C 库。
beginTransmission()、write()、endTransmission()、requestFrom()和read()是其核心函数。 - EEPROM 寻址:EEPROM 按内存库组织。我们在数据之前写入一个内存地址字节。
- 写入周期延迟:EEPROM 需要几毫秒来存储数据。
delay(5)确保写入操作在下一次操作之前完成。
常见陷阱与调试技巧
- 错误的 I2C 地址:仔细检查 EEPROM 地址。常见地址为
0x50到0x57(取决于 A0/A1/A2 引脚)。 - 缺少上拉电阻:在实际硬件中,SDA 和 SCL 需要上拉电阻(4.7kΩ)。Velxio 的虚拟 EEPROM 内部处理了这一点。
- 串口监视器波特率:确保串口监视器设置为 115200 波特率。不匹配会导致乱码。
- 写入周期时序:如果跳过
delay(5),EEPROM 可能无法正确存储数据。如有需要,可增加延迟时间。 - LED 不闪烁:检查接线。红色 LED 连接到 D12,绿色 LED 连接到 D10。两个阴极都连接到 GND。
建议扩展
- 存储和检索传感器数据:读取温度传感器并将最后的值保存到 EEPROM。
- 添加按钮:使用按钮触发读取或写入操作。
- 扩展到 256 字节:修改代码以写入更大的数据块。
- 使用 EEPROM 进行配置:存储校准值或用户设置。
亲自尝试!
准备好实验了吗?在 Velxio 中打开实时示例:
点击编辑器工具栏中的 运行 按钮进行编译和模拟。在控制台中观察串口输出——你应该会看到所有 8 个字节成功读取回来。

使用画布工具栏进行缩放、平移和检查电路。

需要添加更多组件?打开组件选择器浏览零件。

祝模拟愉快!