简介
I2C(集成电路间总线)是一种流行的通信协议,它仅需两根线(SDA 数据线和 SCL 时钟线)就能让微控制器与传感器、显示屏及其他外设通信。但在原型开发时,你往往不知道新 I2C 设备的确切地址。这时 I2C 扫描仪就派上用场了——它会探测总线上所有可能的地址,并报告哪些设备有响应。
在本教程中,我们将使用 Velxio 在线仿真器为 Raspberry Pi Pico 构建一个 I2C 扫描仪。你将学习如何连接一个包含两个指示灯的简单电路,用 Arduino C++ 编写扫描代码,并解读结果。无需硬件,只需浏览器!

电路详解
我们的电路虽简单但富有启发性。我们将使用两个 LED 在扫描过程中提供视觉反馈:
- 蓝色 LED(led-scan):通过限流电阻(集成在 LED 元件内部)连接到 GP12(Pico 的 D12 引脚)。其阳极(A)接 GP12,阴极(C)接地。每次扫描仪在 I2C 总线上发送起始条件时,该 LED 会闪烁。
- 绿色 LED(led-found):连接到 GP10(D10 引脚)。阳极接 GP10,阴极接地。当扫描过程中发现设备时,该 LED 会亮起。
两个 LED 共享 Pico 的 GND.1 引脚作为公共接地。I2C 总线本身使用默认引脚:SDA = GP4 和 SCL = GP5。无需外部上拉电阻,因为 Wire 库会启用 Pico 的内部上拉。
要在 Velxio 中构建此电路:
- 从画布工具栏打开 元件选择器。

- 添加一块 Raspberry Pi Pico 开发板。
- 从“输出”类别中添加两个 LED(蓝色和绿色)。
- 按如下方式接线:GP12 → 蓝色 LED 阳极,GP10 → 绿色 LED 阳极,两个阴极 → GND。
- 使用 画布工具栏 缩放并整齐排列元件。

代码详解
现在让我们深入代码。在 Velxio 中打开代码编辑器,粘贴以下草图:
// Raspberry Pi Pico — I2C Scanner
// Scans I2C bus (Wire / I2C0: SDA=GP4, SCL=GP5) for devices
#include <Wire.h>
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(); // SDA=GP4, SCL=GP5 by default on Pico
Serial.println("=== Pico I2C Scanner ===");
Serial.println("Default I2C0: SDA=GP4, SCL=GP5");
Serial.println();
}
void loop() {
Serial.println("Scanning I2C bus...");
int found = 0;
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
byte error = Wire.endTransmission();
if (error == 0) {
found++;
Serial.print(" Device found at 0x");
if (addr < 16) Serial.print("0");
Serial.print(addr, HEX);
// Identify known addresses
switch (addr) {
case 0x48: Serial.print(" (Temperature sensor)"); break;
case 0x50: Serial.print(" (EEPROM)"); break;
case 0x68: Serial.print(" (DS1307 RTC)"); break;
case 0x27: Serial.print(" (LCD backpack)"); break;
case 0x3C: Serial.print(" (SSD1306 OLED)"); break;
default: break;
}
Serial.println();
}
}
Serial.print("Scan complete. Found ");
Serial.print(found);
Serial.println(" device(s).");
Serial.println();
delay(5000);
}
工作原理
Wire.begin()在默认引脚(GP4/GP5)上初始化 I2C 外设。在 Pico 上,这会设置 I2C0。for循环 遍历所有可能的 7 位地址,从 1 到 127。地址 0 保留用于通用呼叫,因此我们跳过它。- 对于每个地址,我们调用
Wire.beginTransmission(addr),然后调用Wire.endTransmission()。endTransmission()的返回值在设备应答时为 0,否则为非零错误代码。 - 如果设备有响应,我们以十六进制格式打印其地址。代码还包含一个 switch 语句,用于标注一些常见地址(例如,SSD1306 OLED 显示屏的 0x3C)。
- GP12 上的蓝色 LED 在每个扫描周期开始时切换状态(你可以在扫描循环周围添加
digitalWrite(12, HIGH)和digitalWrite(12, LOW)以获得视觉反馈)。GP10 上的绿色 LED 在发现设备时亮起。
要编译并运行,请点击编辑器工具栏中的 编译 按钮。

关键概念
- I2C 协议:一种多主多从、分组交换、单端串行通信总线。每个设备都有唯一的地址。
- Wire 库:Arduino 内置的 I2C 通信库。在 Pico 上,默认使用 I2C0。
- 上拉电阻:I2C 线路需要上拉电阻连接到 VCC。Pico 具有可启用的内部上拉,但为了与多个设备可靠工作,建议使用外部 4.7kΩ 电阻。
- 寻址:7 位地址范围从 0x01 到 0x7F(127)。某些地址是保留的(例如,0x00 用于通用呼叫)。
常见陷阱与调试技巧
- 未发现任何设备? 检查 I2C 设备是否已通电并正确连接。在仿真中,确保已向电路添加虚拟 I2C 外设(如 OLED 或温度传感器)。
- 引脚错误? Pico 的默认 I2C0 引脚是 GP4(SDA)和 GP5(SCL)。如果使用不同引脚,请在
Wire.begin()之前调用Wire.setSDA(pin)和Wire.setSCL(pin)。 - 串行监视器无输出? 确保波特率匹配(我们的代码中为 115200)。在 Velxio 中,从工具栏打开串行监视器。
- LED 不闪烁? 检查接线:阳极接 GPIO,阴极接 GND。同时检查是否在
setup()中使用pinMode(12, OUTPUT)和pinMode(10, OUTPUT)将引脚设置为输出模式。
建议扩展
- 添加真实 I2C 设备:在画布上放置一个 SSD1306 OLED 或 BMP280 传感器,观察扫描仪检测到它。
- 扫描多个总线:Pico 有两个 I2C 外设(I2C0 和 I2C1)。修改代码以扫描两者。
- 在 LCD 上显示结果:不使用串行输出,而是在 16x2 LCD 上显示找到的地址。
- 自动检测并配置:一旦知道设备地址,自动初始化其库。
亲自尝试!
准备好扫描 I2C 总线了吗?在 Velxio 中打开实时示例,开始实验:
无需下载,无需焊接——纯仿真。修改代码,添加新元件,立即查看结果。祝扫描愉快!