I2C标准能带来些啥好处呢?

  1. 简单的2线串行I2C总线最小化互连,节省PCB布板走线空间;
  2. 完全集成的I2C总线协议消除了地址解码器。
  3. I2C总线的多主控能力允许终端用户设备通过外部连接到装配线进行快速测试和校准。
  4. 标准支持广泛,大量无铅封装I2C总线兼容集成芯片进一步降低了空间需求。

时序图

I2C的时序图如下:

cubemxi2s 时钟_cubemxi2s 时钟

 

START事件:可以联想一下UART的起始位,这个用于通知I2C通信的发起。用一句话描述就是在SCL常高时,采集到SDA高到低跳变,这就是启动事件。

数据有效性SDA线上的数据必须在时钟的高周期保持稳定。数据线的高或低状态只能在SCL线上的时钟信号低时改变。每个传输的数据位产生一个时钟脉冲。

ACK:确认信号ACK的定义如下:发送器在ACK时钟脉冲期间释放SDA线,因此接收器可以将SDA线拉低,并在此时钟脉冲的高电平期间保持稳定的低电平(见上图)。须严格遵循电气的建立保持时间,使用时需要用示波器去严格测试信号是否能满足这些参数。

NACK:当在第九个时钟脉冲期间SDA保持高电平时,这被定义为“NACK”信号。 之后主机可以产生停止条件以中止传输,或产生重复的开始条件以开始新的传输。 导致NACK产生的条件有五个:

  1. 总线上没有报文中所包含地址的接收器,因此没有设备响应应答。
  2. 接收器无法执行接收或发送操作,比如它正在执行某些实时功能,并且尚未准备好与主机进行通信。
  3. 在传输过程中,接收器收到应用协议不理解的数据或命令。
  4. 在传输期间,接收器无法再接收更多有效数据字节。比如程序或者芯片内置缓冲区已经满了
  5. 主接收器用NACK通知从发送器结束传输。这是何意呢?比如主设备已经接受到足够多的数据,不希望从设备发送更多的数据时,就可以NACK从设备,这样从设备就会停止发送。

时钟同步与仲裁

时钟同步:两个主机可以同时开始在空闲总线上进行传输,并且必须有一种方法来确定控制总线并完成其传输的方法。 这是通过时钟同步和仲裁完成的。 在单主机系统中,不需要时钟同步和仲裁。

时钟同步是通过I2C接口中SCL线的线与实现的。啥意思呢?

当SCL从高到低的过渡时,总线上的主机开始计数其低电平时间,且一旦主机时钟变为低,它就会将SCL保持在该状态,直到变为高状态为止。

但是,如果另一个主机时钟仍在其低周期内,则此时钟从低到高的转变不会改变SCL线的状态。 所以,SCL线由主机以最长的低电平周期保持为低电平。 低电平周期较短的主机在此期间进入高电平等待状态。

上面的话不好理解?看看线与的本质是与,啥叫与呢? 比如C=A&B,只要其中一个变量A/B为低,那么C就必然为0,比如下图中,即便CLK1(为其中一个主机)为高了,但奈何另一主机的CLK2任然为低啊?所以SCL线上测出来就是低。

当所有相关的主机都计数完低电平周期后,时钟线被释放并变为高电平。 这样,主时钟和SCL线的状态之间就没有区别,所有主时钟都开始计数其高电平周期。 第一个完成其高电平周期的主机将SCL线再次拉低。

cubemxi2s 时钟_数据_02

 这里的几句话需要划重点去理解,这就是I2C总线的核心之核心工作原理:线与!

仲裁:仲裁与同步类似,仅在系统中使用多个主机时才会涉及到,从站不参与仲裁过程。首先要理解一下仲裁是干啥的?所谓仲裁就是在多主机模式下,哪一个主机能获取介质的访问权限,获得权限的主机才可以传输I2C通信报文。 只有在总线空闲时,主机才可以开始传输。 两个主机可以在START的最小保持时间内产生START条件这种情况会导致总线上出现有效的START条件。 然后需要仲裁以确定哪个主机将完成其传输。仲裁是一位一位地进行。 节点发送1个位后,回读比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线

cubemxi2s 时钟_数据_03

 

上图显示了两个主机的仲裁程序。 实际使用中连接到总线的主机数量可能会更多。 当主机产生的DATA1的内部数据电平与SDA线上的实际电平之间存在差异时,DATA1输出将关闭。 从而主机1退出竞争,没有获得总线的控制权。

时钟延长:时钟延长通过将SCL线保持为低电平来暂停事务。 直到再次释放高电平,事务才能继续。 时钟延长是可选的,实际上,大多数从设备不包括SCL驱动能力,因此它们无法延长时钟。

为啥要设计这样一个机制呢?个人理解是为了增强系统的健壮性而设计的:

在字节传输级别,设备可能能够以快速速率接收数据字节,但需要更多时间来存储接收到的字节或准备另一个要发送的字节。此时,从机可以在接收和确认字节后将SCL线保持为LOW,以强制主机进入等待状态,直到从机为握手过程中的下一个字节传输做好准备。

在位级别上,诸如微控制器之类的设备可以通过延长每个时钟的LOW周期来减慢总线时钟。 任何主机的速度都将根据该设备的内部工作速率进行调整。

总线复位

在异常情况下,如果时钟SCL被拉为LOW了,则有哪些办法可以对总线复位呢?

  1. 则优选的做法是如I2C设备具有硬件复位输入,则使用硬件复位信号来复位总线。
  2. 如果I2C设备没有硬件复位输入信号,如果硬件设计可以考虑用MOSFET控制设备电源,重新通电以激活强制性的内部上电复位(POR)电路。
  3. 还有一种做法是主机发送9个时钟SCL脉冲。 使总线保持低电平的设备应在这九个时钟内的某个时间释放它。这个具体怎么做呢?主设备初始化I2C总线时,可以冗余加9个SCL脉冲以复位I2C总线,或者检测到SDA长时间被拉低后,可以以控制IO高低翻转的方式控制SCL产生9个脉冲