对于I^2C这个磨人的小妖精,我们知道在标准模式下它的速率可达100kbit/s,快速模式下可达400kbit/s,飙车模式下可达3.4Mbit/s。一般情况下,I^2C搞搞EEPROM,那是不在话下,完全没有问题。但是如果从设备高级一点,例如处理器之类的,需要飙车模式,slave接到主机命令后需要进行一些高端的操作,然后将结果返回给主机。这时Slave需要根据收到的数据,进行相应的处理,比如把收到的数据存起来,或者处理一下收到的数据再发给Host,等等。
对于这些数据处理,自然是需要时间的,而且处理数据的时间,也只能发生在SCL是低电平的时候,综合上述两点,就可以解释,为何I2C的速率相对其他总线(SPI、UART)来说比较低了。
那这样是否意味着车就此飙不了了呢?
有小伙伴想到增加延时,这不能解决根本问题,而且延时的量不好把握,加多少才是正正好好不多不少呢?这太难了。
那么如何克服这个问题呢?总不能因为处理数据需要时间就降低SCL的速率吧?
答案是clock stretching。当I^2C设备需要更多的时间来处理重要的工作时,这时,从机可以通过将 SCL 保持为低电平来暂停数据传输,直到数据准备好后再释放总线,这就是clock stretching。官方定义如下。
所以当出现如下场景的时候,clock stretching就可以登场了。1)master需要从slave上读数据,但是slave需要花费比较长的时间来准备数据,例如你想要读出温度传感器上的温度,但是这个数据正在转换中。这时就需要clock stretching让数据转换完成,把数据送回主机。2)又或是MCU Master正在进行写操作,但是transmit buffer还没有被填满, Master就需要在等待load下一个字节的时候clock stretching了。也有可能是master正在进行读的操作,而接收端的buffer还没有被读到。这时clock stretching就可以出马暂停总线,直到数据被读到而不是overwrite之前接收到的数据。
说了那么多,我们还是上图比较直观一点。老规矩,结合时序来讲,这样更容易理解。
如下图箭头1所指,从机收到Host发来的地址信息后,开始比对是否与预设的一致,然后再确定该改出ACK还是NACK
如下图箭头2所示从机收到读指令后,需要时间准备数据。
但是,clock stretching虽好,并不是所有的I^2C设备都支持这个option。所以大家在使用之前,一定要先查下相关的data sheet,看下是否支持。