我们的项目需要用到i2c slave,顺其自然就开发slave模式的API程序。
常常使用I2C的Master模式,因为是Master模式,从硬件的角度上看,时钟是我控制的,所以实现起来较为自由。无论是查询模式,还是中断模式,甚至是DMA模式,我推上去的API实现均能很好的支撑应用层的业务。
Master模式的良好实现也为Slave模式的“轻敌”埋下了伏笔。
轻敌一:接收方向
当TR**置位时,其应为slave模式下的发送。这里无须考虑谁是主,谁是从。当前的I2C模块发送就是了。我是做了几回测试,才得出来的结论。
轻敌二:STOP中断
当时,看了slave模式下有STOP中断就认为STOP信号接收时,一定会触发中断。事实是,当Master发送NACK后,并不会再进入STOP中断了。换句话说,当slave接收到NACK中断后,其即代表本轮I2C通讯完成。我的错误程序是一直在等STOP中断才算本次通讯完成,这也就导致我的程序时而由于未等到STOP中断而超时进入了Busy状态。我还采取了重置I2C模块来解决。现在回头看,这显然是不对的。
轻敌三:I2C data 移位寄存器。
还以为当发送中断触发时,立刻填充待发送数据以完成发送。可事实是,MCU会首先发送I2C data移位寄存器里面的内容。换句话说,我们必须首先往I2C data寄存器里面预填充一个字节待发送数据。这样才满足I2C的发送时序要求。并不是中断后,再赋值,也可以简单的理解为I2C data寄存器有1字节的小FIFO。
折腾了三次,调试了几天!如果当时认真的阅读了datasheet与官方示例,估计也不会这么轻敌。
看来只读API,不读datasheet的路子是走不通的,走不通的!
|
|