串行外设接口 (SPI) 是一种同步串行通信协议,可提供非常高速的全双工通信。它 是一种主从类型协议,可在微控制器及其外设之间提供简单且低成本的接口。SPI 接口总线通常用于连接微处理器或微控制器与存储器,如 EEPROM、RTC(实时时钟)、ADC(模数转换器)、DAC(数模转换器)、LCD、音频 IC、温度和压力等传感器,MMC 或 SD 卡等存储卡,甚至其他微控制器。
对于短距离通信,同步串行通信将是更好的选择,尤其是 串行外设接口 (SPI) 是最佳选择。当我们说短距离通信时,通常是指与设备内部或同一板(PCB)上的设备之间的通信。
SPI 是一种同步类型的串行通信,即它使用专用时钟信号来同步发送器和接收器或主从器。发送器和接收器通过单独的数据线和时钟线连接,时钟信号将帮助接收器何时在总线上查找数据。
时钟信号必须由主设备提供给从设备(或在多个从设备设置的情况下提供给所有从设备)。时钟信号上有两种类型的触发机制,用于使接收器了解数据:边沿触发和电平触发。最常用的触发是边沿触发,有两种类型:上升沿(时钟从低到高的转换)和下降沿(从高到低的转换)。根据接收器的配置方式,在检测到边沿时,接收器将从下一位开始在数据总线上查找数据。
由于时钟和数据都是由主机(或发送器)发送的,我们不必担心数据传输的速度。SPI 在其他同步串行通信协议(或任何与之相关的串行通信)中如此受欢迎的原因在于,它以相对较低的成本提供了高速安全数据传输和相当简单的硬件(如移位寄存器)。
SPI 是如何工作的?
SPI 或串行外围接口是摩托罗拉在 1980 年代开发的,作为微控制器(最初是摩托罗拉的微控制器)与其外围 IC 之间的标准、低成本和可靠的接口。由于其简单的接口、灵活性和易用性,SPI 已成为一种标准,很快其他半导体制造商开始在他们的芯片中实施它。在 SPI 协议中,设备在多点接口中以主从关系连接。在这种类型的接口中,一个设备被视为总线的主设备(通常是微控制器),而所有其他设备(外围 IC 甚至其他微控制器)被视为从设备。在 SPI 协议中,可以只有一个主设备,但可以有多个从设备。SPI 总线由 4 个信号或引脚组成。他们是
- Master – Out / Slave – In (MOSI)
- Master – In / Slave – Out (MISO)
- Serial Clock (SCLK) and
- Chip Select (CS) or Slave Select (SS)
注意:不同的制造商对 SPI 总线使用不同的命名法。有关确切信息,请参阅数据表。
由于 SPI 总线是使用 4 条信号或线实现的,因此有时称为四线接口。让我们首先看一个使用 SPI 协议连接的单主和单从之间的简单接口,然后我们将解释 4 线。下图描绘了使用 SPI 总线连接到从属设备(外设)的主设备(处理器)。
Master – Out / Slave – In或 MOSI,顾名思义,就是由 Master 生成并由 Slave 接收的数据。因此,主机和从机上的 MOSI 引脚连接在一起。Master – In / Slave – Out 或 MISO 是 Slave 生成的数据,必须传输给Master。
主机和从机上的MISO引脚都连接在一起。尽管 MISO 中的信号是由 Slave 产生的,但线路是由 Master 控制的。主机在 SCLK 产生一个时钟信号,并提供给从机的时钟输入。片选 (CS) 或从机选择 (SS) 用于由主机选择特定的从机。
由于时钟由主设备生成,因此数据流由主设备控制。对于每个时钟周期,一位数据从主机传输到从机,一位数据从从机传输到主机。这个过程同时发生,在 8 个时钟周期后,一个字节的数据在两个方向上传输,因此,SPI 是全双工通信。如果数据只能由一个设备传输,那么另一个设备必须发送一些东西(甚至是垃圾或垃圾数据),传输的数据是否是实际数据取决于设备。这意味着对于一个设备发送的每一位,另一个设备必须发送一位数据,即主设备同时在 MOSI 线上发送数据并在 MISO 线上从从设备接收数据。如果从机要发送数据,主机必须提前知道从机何时要发送数据,从而产生相应的时钟信号。如果必须将多个从站连接到主站,则设置将类似于下图。
即使多个从机通过 SPI 总线连接到主机,但任何时候只有一个从机处于活动状态。为了选择从机,主机将拉低相应从机的SS(从机选择)或CS(芯片选择)线。因此,主设备上必须有一个单独的 CS 引脚对应每个从设备。我们需要拉低 SS 或 CS 线来选择从机,因为这条线是低电平有效。
SPI 设备间的数据传输之所以又被称为数据交换,是因为 SPI 协议规定一个 SPI 设备不能在数据通信过程中仅仅只充当一个 "发送者(Transmitter)" 或者 "接收者(Receiver)"。在每个 Clock 周期内,SPI 设备都会发送并接收一个 bit 大小的数据(不管主设备好还是从设备),相当于该设备有一个 bit 大小的数据被交换了。一个 Slave 设备要想能够接收到 Master 发过来的控制信号,必须在此之前能够被 Master 设备进行访问 (Access)。所以,Master 设备必须首先通过 SS/CS pin 对 Slave 设备进行片选, 把想要访问的 Slave 设备选上。 在数据传输的过程中,每次接收到的数据必须在下一次数据传输之前被采样。如果之前接收到的数据没有被读取,那么这些已经接收完成的数据将有可能会被丢弃,导致 SPI 物理模块最终失效。因此,在程序中一般都会在 SPI 传输完数据后,去读取 SPI 设备里的数据, 即使这些数据(Dummy Data)在我们的程序里是无用的(虽然发送后紧接着的读取是无意义的,但仍然需要从寄存器中读出来)。
SPI只有主模式和从模式之分,SPI没有读和写的说法,因为实质上每次SPI是主从设备在交换数据。也就是说,你发一个数据必然会收到一个数据;你要收一个数据必须也要先发一个数据。
SPI硬件
与 UART 和 I2C 相比,实现 SPI 的硬件要求非常简单。考虑一个 Master 和一个 Slave 使用 SPI 总线连接。下图显示了这两种设备的最低系统要求。
从图中可以看出,主器件由一个移位寄存器、一个数据锁存器和一个时钟发生器组成。从机由类似的硬件组成:移位寄存器和数据锁存器。两个移位寄存器相连形成一个回路。通常,寄存器的大小为 8 位,但更大的 16 位寄存器也很常见。在时钟信号的上升沿期间,两个设备(主设备和从设备)都将输入位读入寄存器的 LSB。在时钟信号的负周期期间,主机和从机都在移位寄存器的 MSB 的相应输出上放置一个位。因此,对于每个时钟周期,在每个方向(即从主设备到从设备以及从设备到主设备)传输一个数据位。因此,从每个设备传输一个字节的数据需要 8 个时钟周期。
SPI 操作模式
我们已经看到,主设备的工作是生成时钟信号并将其分配给从设备,以便在主设备和从设备之间同步数据。主机的工作并没有结束于产生特定频率的时钟信号。事实上,主从必须就某些同步协议达成一致。为此时钟信号通过时钟极性 (CPOL) 和 时钟相位 (CPHA) 控制着两个 SPI 设备间何时数据交换以及何时对接收到的数据进行采样,来保证数据在两个设备之间是同步传输的。
时钟极性决定时钟的状态。极性,会直接影响SPI总线空闲时的时钟信号是高电平还是低电平。
CPOL = 1:表示空闲时是高电平;
CPOL = 0:表示空闲时是低电平。
一个时钟周期会有2个跳变沿。而相位,直接决定SPI总线从那个跳变沿开始采样数据。
CPHA = 0:表示从第一个跳变沿开始采样;
CPHA = 1:表示从第二个跳变沿开始采样。
SPI总线传输的四种模式
CPOL 和 CPHA 的不同组合,形成了SPI总线的不同模式。
时钟极性CPOL是用来配置SCLK的电平出于哪种状态时是空闲态或者有效态,时钟相位CPHA
是用来配置数据采样是在第几个边沿:
CPOL=0,表示当SCLK=0时处于空闲态,所以有效状态就是SCLK处于高电平时。
CPOL=1,表示当SCLK=1时处于空闲态,所以有效状态就是SCLK处于低电平时。
CPHA=0,表示数据采样是在第1个边沿,数据发送在第2个边沿。
CPHA=1,表示数据采样是在第2个边沿,数据发送在第1个边沿。
例如:
CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是
SCLK由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。
CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是
SCLK由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。
CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是
SCLK由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。
CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是
SCLK由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。
SPI 配置
有两种类型的配置可以将 SPI 设备连接到 SPI 总线中。它们是独立从配置和菊花链配置。在独立从配置中,主设备为所有从设备提供专用的从设备选择线,每个从设备都可以单独选择。从机的所有时钟信号都连接到主机 SCK。同理,所有从机的所有 MOSI 管脚都连接到主机的 MOSI 管脚,所有从机的所有 MISO 管脚都连接到主机的 MISO 管脚。
在菊花链配置中,只有一条从属选择线连接到所有从属。主机的 MOSI 连接到从机 1 的 MOSI。从机 1 的 MISO 连接到从机 2 的 MOSI,依此类推。最后一个slave的MISO连接到master的MISO。考虑主机将 3 个字节的数据传输到 SPI 总线。首先,第一个字节的数据被转移到从站 1。当第二个字节的数据到达从站 1 时,第一个字节被推入从站 2。最后,当第 3 个数据字节到达第一个从机时,第一个数据字节被移入从机 3,第二个数据字节被移入第二个从机。如果master想要从slave获取信息,它必须发送3个字节的垃圾数据给slave,以便slave中的信息到达master。
SPI的应用
- 内存:SD卡,MMC,EEPROM,闪存
- 传感器:温度和压力
- 控制设备:ADC、DAC、数字 POTS 和音频编解码器。
- 其他:相机镜头卡口、触摸屏、LCD、RTC、视频游戏控制器等。
优点
- SPI 实现起来非常简单,硬件要求也没有那么复杂。
- 始终支持全双工通信。
- 非常高的数据传输速度。
- 由于使用了 CS 或 SS,因此无需为从机提供单独的地址。
- 仅支持一台主设备,因此不会发生冲突。
- 来自主机的时钟是根据从机的速度配置的,因此从机不必担心时钟。
缺点
- 每个额外的从设备都需要一个额外的主设备专用引脚用于 CS 或 SS。
- 没有确认机制,因此没有确认收到数据。
- 最慢的设备决定了传输的速度。
- 没有官方标准,因此经常用于特定于应用程序的实现。
- 没有流量控制。
SPI协议读写操作
主机设备在访问从机设备前,必须将SS信号拉低,使能从机设备;当主机要结束本次通信时,再把SS信号拉高即可。
程序中我们都是通过寄存器操纵Tx/Rx FIFO,数据串行化工作由SPI硬件完成(分为手动和自动两种设置)。由于SPI协议“时钟驱动”和“数据交换”的特点,当主机向TxFIFO写数据,进行数据传输时,同时也会把接收到的数据存储到RxFIFO中。下一次传输之前我们应该将RxFIFO中的全部数据都读取出来。
SPI的读、写是同时进行的。如果我们只希望进行写操作,则忽略接收到的字节即可;如果要读取从机中的数据,由于从机无法主动发送数据,因此需要主机向从机发送空字节,来引导从机的传输。
SPI协议的优缺点
SPI的最大优点是速度快(是UART的几十倍),这也是EEPROM、Flash等芯片采用SPI接口的原因。比如我们将比较大的FPGA bin文件烧写到Flash中,用的便是SPI协议。其支持连续传输模式,无需不断检测帧的起始与结束,同步传输的效率比异步传输也要高。
SPI的缺点主要是抗干扰能力比RS422/485要差,不适合远距离传输。另外没有与IIC协议类似的应答机制,以告诉用户是否收到了数据。编程实现上比UART要困难一些,因为我们平时使用的EEPROM、Flash等都提供了现成的命令格式,按照时序图设计即可。当我们自定义主机和从机间的通信时,还要根据设计目的定义一些命令。