本帖最后由 qiushenghua 于 2015-3-18 18:15 编辑
仙猫 发表于 2015-3-18 09:28
关于单向SCL芯片的必要性说两点:
① 单向SCL芯片存在的必要性是明确的,事实上在一般应用中单主机构成占绝对多数,很多只能作从机用的Device(比如I2C型存储器,I/O扩展器等)芯片,SCL引脚本来就是单向的,为此有一颗廉价芯片,其量产效果会是显著的。
② 这点俺没搞清(如通过这次搞清了则是参与讨论的最大收获),一直认为规程上从机不会也没必要主动拉死SCL,因为从机可在SDA线上利用回复主机的ACK/NAL之际表明自己的状态。若确实如此,则该怀疑集成系统里的从机程序有没问题了——这里又可想象两种情况:
②-1 因从机编程的疏忽,使得SCL有瞬间输出给主机造成了干扰。(比如MCU初始化I/O时先设为输出,再给初始值的毛糙做法并不鲜见。)
②-2 该从机是智能型的,上电后若发现没其他主机,自己就华丽转身变为主机。——如是这样,SCL就必须双向了,双向SCL本来就是为多主机而存在的。
从机可在SDA线上利用回复主机的ACK/NAL之际表明自己的状态。
——若从机主频很低,在主机拉高时钟之前来不及响应ACK/NACK,那么通信就会被中断。
举例来说,先假设SCL是单向的,我们知道在I2C通信时从机要先响应地址,一般会在接受完整个地址后判断是否与本机一致,是否响应通信请求。
假如主机刚发送完从机地址,此时主机需要释放SCL,采样ACK、NACK信号。如果此时时钟线为高电平,那么同时数据线的内容就作为ACK/NACK信号。
如果我们使用的是一个低速的从机设备,那么在主机拉高SCL线的时候从机实际上很有可能并未完成对Slave地址的判断。如果是双向时钟,那么从机可以通过拉低时钟线阻止主机的采样ACK/NACK。如果是单向时钟,那么即使Slave地址与本机一致,主机采样到的也会是NACK信号(从机来不及拉低SDA线),那么从机会响应后面的时钟序列发送数据(它以为自己发的是ACK),主机却不知道收到什么样的数据(开始发送下一次通信的slave地址)。
总结一下,双向的SCL线能保障I2C通信是以主从双方能够接受的最大速率进行数据传输。你举例的 I2C型存储器由于从机速率比主机快,所以他们能接受的最大通信速率就是主机的时钟频率,而本例中从机响应速率不及主机,所以从机拉低时钟线暂停数据传输是必要的。
很多人在写I2C程序的时候模仿UART的程序,严格按照固定时钟间隙来采样或者翻转SCL线。这实际上并不符合I2C通信的设计原理。I2C通信主机不能自顾自的发送信号或者读取信号,还需要实时关注总线上的电平是不是达到了自己的设定值。等会我分享一段之前用状态机写的I2C通信函数,供大家参考。
|