I2C 写的时序是(截图来自友晶科技Terasic书 《DE2-115实战宝典》): 

 

读的时序是:

 

也就是读的过程是:

  • 发送起始位;
  • 发送slave地址+write bit set;
  • 发送内部寄存器地址;
  • 重新发送起始位,即restart;
  • 重新发送slave地址+read bit set;
  • 读取数据
    主机接收器在接收到最后一个字节后,也不会发出ACK信号。于是,从机发送器释放SDA线,以允许主机发出P信号结束传输。 
  • 发送停止位   

 但我很好奇为啥读的时候这么麻烦, 要发送好几次地址呢?后来查资料才知道,这里存在一个叫做哑写(Dummy Write )的操作,目的是为了 更新 I2C 从设备的微控制器 的内部字节地址计数器( internal address counter)。

 

 

 为什么会有哑写的操作呢?跟字节地址计数器有什么关系?

这就要先了解I2C 从设备的一些特性。拿DE2-115 开发板的 EEPROM器件 24LC32来说, 它支持当前地址读和随即地址读, 以及 连续读操作 这三种模式。 I2C 从设备的微控制器 的内部字节地址计数器 会根据每读一个数据或者写一个数据就累加1,直到累加到31(写操作) 或者是累加到页尾(读操作)。

如果直接发送器件地址(也就是进行当前地址读),那么它读出来的是当前计数器所指的地址:(因为只要不断电,the internal address counter  就会保持之前的值, 比如之前先对计数器0指的地址写了一个数据,此时计数器会累加到1, 然后接着进行当前地址读操作,此时读出的数据将是计数器1所指的地址的数据。

 

 那为了能直接读取指定地址的数据, 可以先对字节地址计数器进行归零操作,也就是先进行哑写操作:

  • 发送起始位;
  • 发送slave地址+write bit set;
  • 发送内部寄存器地址;

 

此时字节地址计数器为0,那么读取的数据就是指定地址的数据了,这种方式也就是  24LC32的 随机地址读 模式: