You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

I2C协议中的‘Dummy Read’是什么?

关于I2C中"Dummy Read"的解释(结合SH1106 OLED)

嘿,刚好我对SH1106的I2C操作熟得很,来给你把这个"Dummy Read"讲明白。

首先,直白点说:Dummy Read就是一次“凑数”的I2C读操作——你发起读请求,但完全不使用读回来的数据,它的唯一作用是帮设备把内部状态调整到正确位置,为后续的有效数据读取铺路。

结合你提到的SH1106数据手册第29页的内容,咱们拆解下为什么读RAM时需要它:

读取显示数据——从列地址和页地址指定的显示RAM区域读取8位数据。每次写入后列地址会自动加1,微处理器可连续读取多字数据。单次Dummy Read……

当你要读SH1106的显示RAM时,第一步肯定是先通过I2C写操作,把目标的页地址和列地址设置好对吧?这时候设备内部的地址指针已经指向了你要读的起始位置,但这里有个关键:SH1106的I2C接口从“写模式”切换到“读模式”时,需要一个周期来同步内部地址指针和数据输出寄存器。

所以当你刚完成地址设置,立刻发起读操作时,第一次读回来的字节根本不是你要的RAM数据——它只是设备在切换模式时输出的无效占位数据,这就是所谓的"Dummy Read"。你必须把这个字节扔掉,不能用它。

等做完这次Dummy Read之后,后续的连续读操作就正常了:每读一个字节,列地址自动加1,读出来的就是你要的显示RAM数据,完全符合手册里说的连续读取多字数据的逻辑。

给你举个实际代码的例子(用Arduino的Wire库),一看就懂:

// 第一步:设置要读取的页地址和列地址(写操作)
Wire.beginTransmission(SH1106_I2C_ADDR);
Wire.write(0x00); // 控制字节,表明后续是命令
Wire.write(0xB0 | target_page); // 设置目标页地址
Wire.write(target_col & 0x0F); // 列地址低4位
Wire.write(0x10 | ((target_col >> 4) & 0x0F)); // 列地址高4位
Wire.endTransmission();

// 第二步:执行Dummy Read,切换到读模式并同步状态
Wire.requestFrom(SH1106_I2C_ADDR, 1); // 请求读取1字节
Wire.read(); // 直接扔掉这个无效数据,这就是Dummy Read

// 第三步:读取有效显示RAM数据
uint8_t ram_data[128]; // 一页是128字节
for (int i = 0; i < 128; i++) {
  if (Wire.available()) {
    ram_data[i] = Wire.read(); // 这里读的就是正确的RAM数据了
  }
}

最后提一句:不是所有I2C设备都需要Dummy Read,但像SH1106这类OLED控制器,因为内部的硬件设计,这一步是必须的——跳过它的话,第一次读出来的数据肯定是错的,甚至会导致后续的连续读取全部偏移。

内容的提问来源于stack exchange,提问作者noearchimede

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:00:27