I2C总结(单主机和多主机)

I2C在使用过程中单个主机是不论是硬件I2C还是硬件I2C都不太难,理解好时序很容易实现。还有就是很多人认为硬件I2C有很多缺点,其实这是谬论吧,硬件I2C在稳定性上胜过软件I2C,而且不占用MCU时间,可以实现I2C中断。如果系统有硬件I2C,那一定选用硬件I2C。多主机I2C有点复杂,需要注意的就是时钟同步和总线仲裁。

一、I2C总结

主机发送数据到从机的状态下:主机控制SCL信号线和SDA信号线,从机只是在SCL线为高的时候去被动读取SDA线。
主机读取从机的数据的状态下:主机来发出时钟信号,从机只是保证在时钟信号为高电平的时候的SDA的状态而已。
SDA和SCL已经通过上拉电阻被上拉,master可以控制(拉低或者释放)这两条线,而slaver只能控制SDA线。当master发送数据时,master会适时地将SDA和SCL拉低或释放(拉高)。确切的时序应该是这样的:
当mater要发送一个start时,mater会将SDA拉低,这就可以了,因为此时的SCL一定是High。好了,一个start就这样发出去了。而slaver也会发现这个start信号的发生,slaver便会准备好接收接下来的数据了。紧接着,master要发送一个Byte的数据了,一位一位的发出这8个bits。这时master会先将SCL拉低,然后在SCL为低的状态下将一个bit准备好放到SDA上(比如要发送一个 0,master就会通过拉低SDA来放好这个0),然后master会把SCL拉高(释放),此时slaver会立刻检测到SCL的变化,由此聪明的slaver便知道master已经将要发送的那个bit准备好了,slaver便会在这个SCL的高电平期间尽快(maser不会等你很久的哦)去读取一下SDA,嗯读到了一个0,slaver就把这个0放到自己的移位寄存器中待后续处理。master会在一个设定好的时间后把SCL再次拉低,然后在SCL为低电平期间把下一个bit放到SDA上,然后再把SCL拉高,然后slaver在SCL的高电平期间再去读SDA。。。。。如此反复8次,一个Byte的传输便告结束。当这8个bit发完后,SCL是处于低电平的(被master拉低的),SDA是出于高电平的(master已经释放了SDA)。
当一个字节发送完毕后,master会释放SDA(拉高)并拉低SCL,此时slaver如果打算发出一个ACK的话,它必须在这个SCL被master拉低的短暂时间内去主动将SDA拉低并保持住 (此前我们说过,SDA此时已经被master释放,所以slaver才有机会去拉低这个SDA)。master会在一个确定的时间后再次将SCL拉高,并在拉高的期间去读取SDA线的状态,如果读到低电平,则认为收到了来自slaver的响应(ACK),否则认为slaver没有响应(NACK)刚才发送的那一个Byte。这个过程就是我们说的i2c通讯中的第9个时钟周期。当master读完这个ACK / NACK 后,会再次将SCL拉低,用以通知slaver:第9个时钟周期已经结束,你现在可以释放SDA了。而此时master也可以向SDA上准备下一个Byte的第一个bit。继而重复上述过程。。。。。或者,master也许想在接下来发送一个stop过去,那么master会在这个SCL为低的时间内将SDA拉低,而后再将SCL拉高,在SCL为高的期间再将SDA释放 (拉高) 。这样,一个STOP位就产生了。你会发现此后的SDA和SCL都是高,这就是是所谓的总线空闲了!
一句话:SCL是单向的,由master控制。而SDA是双向的,master可以控制,slaver也可以控制。
阅读上述过程时,始终牢记:SDA上的数据必须在SCL为高电平期间保持稳定,SDA上的数据只能在SCL为低电平期间变化。(开始信号和结束信号例外)!

另外,需要注意的是,并非每传输8位数据之后,都会有ACK信号,有以下3种例外:
(1)当从机不能响应从机地址时(例如它正忙于其他事而无法相应I2C总线的操作,或者这个地址没有对应的从机),在第9个SCL周期内SDA线没有被拉低,即没有ACK信号。这时,主机发出一个P信号终止传输或者重新发出一个S信号开始新的传输。
(2)如果从机接收器在传输过程中不能接收更多的数据时,它也不会发出ACK信号。这样,主机就可以意识到这点,从而发出一个P信号终止传输或者发出一个S信号开始新的传输。
(3)主机接收器在接收到最后一个字节后,也不会发出ACK信号。于是,从机发送器释放SDA线,以允许主机发出P信号结束传输。

二、I2C 总线的时钟同步与总线仲裁

I2C 总线的 SCL 同步时钟脉冲一般都是由主控器发出作为串行数据的移位脉冲。 每当 SDA 上出现一位稳定的数据后, 在 SCL 上发送一个高电平的移位脉冲。
1. SCL 信号的同步
时钟同步是通过 I2C 接口中 SCL 线的线与实现的。啥意思呢?
如果被控器希望主控器降低传送速度可以通过将 SCL 主动拉低延长其低电平时间的方法来通知主控器,当主控器在准备下一次传送发现 SCL 的电平被拉低时就进行等待, 直至被控器完成操作并释放 SCL 线的控制控制权。 这样以来, 主控器实际上受到被控器的时钟同步控制。 可见 SCL 线上的低电平是由时钟
低电平最长的器件决定; 高电平的时间由高电平时间最短的器件决定。 这就是时钟同步, 它解决了 I2C总线的速度同步。
I2C总结(单主机和多主机)_第1张图片

2. I2C 总线上的总线仲裁
如果在同一个 I2C 总线系统中存有两个主控器, 其时钟信号分别为 SCK1、 SCK2, 它们都具有控制总线的能力。 假设两者都开始要控制总线进行通信, 由于“线与”的作用,在总线做出仲裁之前, 两个主控器都会以“线与”的形式共同参与 SCL 线的使用, 速度快的主控器 1 等待落后的主控器 2 。
对于 SDA 线上的信号的使用, 两个主控器同样也是按照“线与”的逻辑来影响 SDA 上的电平变化。 假设主控器 1 要发送的数据 DATA1 为“101 ……”; 主控器 2 要发送的数据 DATA2 为“1001 ……”。 总线被启动后两个主控器在每发送一个数据位时都要对自己的输出电平进行检测, 只要检测的电平与自己发出的电平一致, 他们就会继续占用总线。 在这种情况下总线还是得不到仲裁。 当主控器 1 发送第 3 位数据“1”时( 主控器 2 发送“0”) , 由于“线与”的结果 SDA 上的电平为“0”, 这样当主控器 1 检测自己的输出电平
时, 就会测到一个与自身不相符的“0”电平。 这时主控器 1 只好放弃对总的控制权; 因此主控器 2 就成为总线的唯一主宰者。

①对于整个仲裁过程主控器 1 和主控器 2 都不会丢失数据;
②各个主控器没有对总线实施控制的优先级别;
③总线控制随即而定, 他们遵循“低电平优先”的原则, 即谁先发送低电平谁就会掌握对总线的控制权。
根据上面的描述, “时钟同步”与“总线仲裁”可以总结如下规律:
①主控器通过检测 SCL 上的电平来调节与从器件的速度同步问题——时钟同步;
②主控器通过检测 SDA 上自身发送的电平来判断是否发生总线“冲突”——总线仲裁。
因此, I2C 总线的“时钟同步”与“总线仲裁”是靠器件自身接口的特殊结构得以实现的。

I2C总结(单主机和多主机)_第2张图片

对于连续访问的数据数量是由主控器来控制的, 具体地说是通过向外围器件发送“非应答信号”来结束这个数据的操作。 对于数据块的“读、 写操作”要注意两点:
( 1) 在读操作中要发送两次命令字: 第一个是带有外围器件地址的“写”命令(R/W=0) , 作用是将后续发出的内部地址写入到外围器件中的“地址计数器”中, 第二个是发送带有外围器件的“读”命令( R/W=1),
开始真正的“读操作”。 两个命令字之间是一个“启动信号 S”来分割的;
( 2) 在写操作中, 某些外围器件( 如 EEPROM) 其连续写入的数据是受到限制的, 如 24C02 每次连续写入的数据不能超过 8 个字节( 这与其内部输入缓冲器的数量有关)。

你可能感兴趣的:(通信,通信协议)