源码如下。
个人总结:
1.I2DR寄存器的读
I2DR寄存器的读操作如下,它与while(size--)中的size无联系,让我一开始觉得I2DR里面的数据就是不变的嘛!
*buf++ = base->I2DR;//I2C读数据
后来我查看了I.MX6ULL里面这样描述I2C的I2DR寄存器:“reading the dataregister allows a read to occur and initiates the next byte to be received”。单从这句可得出,读取I2DR寄存器的行为,不仅仅只是做了“读取数据”的行为,它还触发了I2DR寄存器存储的数据更新,这个数据就是接收的下一个字节。
2.I2DR寄存器的写
I2DR寄存器的写操作如下。
base->I2DR = *buf++;//I2C写数据
很奇怪,手册里没有同样的话来描述写操作。但是有一句话这样描述I2DR的数据域 “Holds the last data byte received or the next data byte to be transefered”。那就姑且也认为:写I2DR寄存器的行为,不仅仅是做了“写数据”的行为,它还触发了I2DR寄存器存储的数据更新,这个数据就是将要发送的下一个字节。
3.I2DR寄存器读与写之后均需等待数据传输完成
根据以上两点分析,I2DR更新数据的过程我认为就是数据传输的过程,而这种传输时间的开销不可忽略,所以每次读或写之后,均需要进行如下等待操作。
while(!(base->I2SR & (1 << 1 )));//等待传输完成
4.假读
I.MX6ULL手册有提到:
A dummy read of I2C_I2DR in Slave Receive mode releases SCL, allowing the master to send data.
我也在stackoverflow上面找了了关于dummy read解释,仅供参考。
This read is not a true read of the I2C bus, but is a read of the IICD register in the IIC block. It will not be seen on the bus or in any I2C specification because it is internal to the design of the I2C hardware block. The I2C hardware block includes a state machine that will perform an IIC byte transfer on the bus each time the IICD register is written to or read. The first byte (I2C device address) is sent out when the I2C address value is written to the IICD register. Once this has been written out then it needs the Dummy Read to initiate the transfer of the next byte. Note that it is a Dummy Read because there is no real data in the IICD register yet because the hardware has not actually done the transfer.
5.接收1个字节发送NACK信号
这个是我的疑惑点。