I2C总线是一种非常基本和常用的总线接口。
不仅如此,还有非常多基于I2C的总线接口,比如SMBus,IPMI,PMBus等。
I2C总线在物理上由两根线构成,一根数据线,一根时钟线。
I2C总线连接的设备有微处理器,LCD,LED,GPIO,EEPROM,RTC,AD/DA转换器等等,下面是一个例子:
还有更复杂的例子,I2C还可以通过Switch等进行扩展:
一般系统中可以有一个或多个I2C控制器,多个I2C控制器就可以扩展出多条I2C总线,不同总线间互不干扰。
I2C总线上的设备分为主从两种类型,主设备是主动发起I2C业务的那个设备,I2C请求的方式是主设备发起数据传输并激活时钟信号来允许这次数据传输。
每个I2C设备都有一个唯一的地址(相对于该总线,因为I2C总线在一个系统中可以有多条),主设备通过I2C地址访问从设备。
主从设备并不固定,有些设备可以做主设备也可以做从设备,当然有的设备只能选择其一。
I2C总线也支持多主设备,即多个设备可以同时发起I2C业务。
多主设备存在的情况下,依赖于时钟同步和仲裁来确定此时此刻谁能够获取I2C的控制权。
I2C总线协议规定了如下的内容:
所以I2C业务的开始和结束都有数据线和时钟线的规范:
业务起始时时钟线拉高,数据线下降沿。
业务结束时时钟线拉高,数据线上升沿。
中间是数据的传输。
数据传输时,时钟信号固定频率高低电平切换,高电平时获取到的数据线电平表示实际的1(高电平)和0(低电平),数据线在时钟拉低时可以变化数据:
一次数据传输包含8个比特,之后接一个ACK位,发送者释放数据线,等待接收者拉低数据线,表示接收者已经成功接收数据,发送者可以接着传送数据。
如果数据线没有被拉低而是一直保持高,表示NACK,有可能是以下情况中的一种:
在多主设备同时使用I2C总线时,需要依赖于时钟同步和仲裁,具体不介绍。
设备访问涉及到地址,需要注意地址也是在数据线上传输的,它跟在业务起始信号之后。
I2C地址有7位和10位两种情况,需要注意的是前面提到过I2C上一次数据的收发是8个字节,所以7位地址信号的传输需要1个字节,10位地址信号的传输需要2个字节。
紧跟地址之后是读写位,表示主设备的操作方向。下面是7位地址的例子:
下面是10位地址的例子:
下面是一次完整的数据传输:
某些I2C地址是保留的,它们有特殊的用途,如下所示:
其中的general call address表示发送给I2C总线上的所有设备。
如果这些设备不需要数据,则不发送ACK信号,否则就发送ACK并作为从设备。
如果在发送general call之后,接着发送一个06h,表示软复位I2C总线上的设备(有些设备没有这个功能,那就不需要复位)。
Device ID用来获取I2C设备信息,具体格式如下:
I2C数据传输的速度,在默认情况下是100kbit/s,后续可以设置成不同的值:
通常情况下I2C的速度相比CPU来说非常的慢,即使是以它的最大速度来讲。
并且有时因为硬件信号上的原因,如果设置的速度较高,会导致数据传输异常。
I2C总线就是两根线。
通常情况下,系统中一般有默认的I2C控制器,软件需要操作的是控制器寄存器。
另外,还可以通过GPIO来模拟I2C,此时就需要软件通过GPIO来操作相关的电平,以实现I2C总线功能。
以Intel型号为Z370的PCH为例,其中包含如下的I2C控制器:
从这里也可以看到它们是跟GPIO复用的,所以也可以配置成GPIO,然后自己来实现I2C,不过似乎也没有特别的必要。
目前没有可以参看的I2C控制器的寄存器说明,所以具体软件操作方式省略。
I2C的传输速度很慢,所以很方便可以通过外部的工具来查看具体的数据传输。
比如将示波器接在数据和时钟线上,即可以查看所有的数据。
此外,还有专门的工具来连接到I2C总线上,然后另一端接在电脑上,通过电脑上的工具来读取I2C业务,比如如下的工具:
使用这样的工具可以很方便的定位I2C总线相关的问题。
《I2C-bus specification and user manual.pdf》
《200-series-chipset-pch-datasheet-vol-1.pdf》