大家知道,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的 随机地址读 模式: