I2C(smbus、pmbus)和SPI协议分析

时间:2021-07-17 05:11:41

I2C和SPI作为两种非常常用的低速外部总线,已经不是什么新新技术了。
有些知识点,明白了,一段时间不用了,又忘记了。所以决定乘最近正好碰过这两个东西,还是写下来以备后患。

I2C

I2C是以前的飞利浦半导*定的标准,也就是如今的NXP。

I2C总线由一条数据线(SDA)和一条时钟线(SCL)组成。设备分主从,主设备提供时钟,并发起操作。
I2C(smbus、pmbus)和SPI协议分析

看一下这张I2C协议必须和可选的功能表。最简单的模式的话,只需要实现4个功能,start、stop、ack、7bit address。
I2C(smbus、pmbus)和SPI协议分析

当scl为高时,sda下拉表示start。当scl为低时,sda上拉表示stop。
I2C(smbus、pmbus)和SPI协议分析

根据下面这个图,我们来讨论这4个基本功能。

  • master控制sda、scl:发起一个start标记
  • master控制sda、scl:start之后的1-7位表示的是slave设备的7bit address
  • master控制sda、scl:第8位表示是读(1)还是写(0)操作,所以我们其实可以把7bit address和这1bit读写位结合起来当成一个byte。
  • master控制scl,slave控制sda:slave强制拉低sda来表示第9位为ack

I2C(smbus、pmbus)和SPI协议分析

分析好了这第一个byte的内容,就可以继续后面更复杂的了。这个时序一共进行了2个byte的写操作。
- master控制sda、scl:start
- master控制sda、scl:7位地址
- master控制sda、scl:1位写
- master控制scl,slave控制sda:slave ack
- master控制sda、scl:1字节数据
- master控制scl,slave控制sda:slave ack
- master控制sda、scl:1字节数据
- master控制scl,slave控制sda:slave ack
- master控制sda、scl:stop
I2C(smbus、pmbus)和SPI协议分析

再看个读操作的
- master控制sda、scl:start
- master控制sda、scl:7位地址
- master控制sda、scl:1位读
- master控制scl,slave控制sda:slave ack
- master控制scl,slave控制sda:1字节数据
- master控制sda、scl:master ack
- master控制scl,slave控制sda:1字节数据
- master控制sda、scl:master ack
- master控制sda、scl:stop
I2C(smbus、pmbus)和SPI协议分析

纯粹的读和纯粹的写我们都会了,下面就要读写混合了。最常见的场景就是通过I2C从设备那读取某个寄存器的值。
- master控制sda、scl:start
- master控制sda、scl:7位地址
- master控制sda、scl:1位写
- master控制scl,slave控制sda:slave ack
- master控制sda、scl:1字节数据
- master控制scl,slave控制sda:slave ack
- master控制sda、scl:start
- master控制sda、scl:7位地址
- master控制sda、scl:1位读
- master控制scl,slave控制sda:slave ack
- master控制scl,slave控制sda:1字节数据
- master控制sda、scl:master ack
- master控制sda、scl:stop
I2C(smbus、pmbus)和SPI协议分析

基本功能的I2C介绍就这些了,但是刚才说到I2C还有许多的可选功能,譬如clock stretching功能,这次就遇到一个bug和这个功能有关。

我们再来看看刚才看过的这个图,在第一个byte传输完之后的一段时间内,scl为低。为什么会出现这种情况那?其实不一定是在第一个字节之后,也可能是master要从slave那读取某个寄存器的值,第一个字节的slave address发过去了,然后第二个字节的寄存器地址又发过去了,后面就该slave来返回一个byte的数据了。但是可能这个数据并不是那么简单的得到的,slave可能会先进入中断,然后做一些计算才能得到要返回的值,而这个计算又比较耗时。那slave可以强制拉低scl来表示现在我在忙,要等我做完事情了才可以继续返回数据。假如slave有这种功能,而master又不支持,那就完蛋了,数据全乱了。幸好,我们的master是CPLD的,通过修改支持了这个功能,操作就正常了。
I2C(smbus、pmbus)和SPI协议分析

SMBUS

SMBUS是一种基于I2C而扩展出来的协议。有一些更为复杂的操作,但是原理都还是基于I2C的。
I2C(smbus、pmbus)和SPI协议分析

I2C(smbus、pmbus)和SPI协议分析

I2C(smbus、pmbus)和SPI协议分析

PMBUS

PMBUS是基于SMBUS,定义了很多和电源管理相关的命令。在物理传输上,和SMBUS是完全一致的。

SPI

SPI有四根线,一根时钟,一根收数据,一根发数据,一根片选。当有多个设备时,他就需要多根片选,所以相比I2C而言,布线更为复杂。
I2C(smbus、pmbus)和SPI协议分析

SPI只规定了如何收发数据,但是数据的具体格式含义并没有定义。譬如在I2C中跟在7位地址后面的1位表示读写,所有设备都需要遵循。但是SPI不是这样,每个slave都有自己定义的数据格式,各不相同。我们先看看下面这个例子。master发送的第一个字节里01表示写,而05表示读。根据第一个字节的不同,slave会做出不一样的响应。
I2C(smbus、pmbus)和SPI协议分析
I2C(smbus、pmbus)和SPI协议分析
而我还见过一种是slave规定,master发给slave的前两个字节代表寄存器的地址,但是0-15位的第15位不当地址来用,而当读写位来用,但是我找不到这个例子的时序图了。我举这个例子是想说明SPI传输数据必须要根据slave设备的timing来,不可想当然。