引子
串行外设接口(Serial Peripheral Interface Bus,SPI)是一种常用于单片机的同步串行通信接口规范,常见使用 SPI 的外设有 Flash(如 W25Qxx)、传感器(如 MPU9250)、LCD。相较于 IIC,SPI 通信速率通常更快(IIC 常见的快速模式即 400kbit/s,而 SPI 的通信速率取决于器件),并且推挽输出能够使得 SPI 拥有更高的传输速率(IIC 为开漏输出,线路更复杂),但线路通常更多(IIC 通常仅需 SCL、SDA,双工下三线 SPI 需要 SCK、MOSI、MISO),并且 SPI 为事实标准,不同厂家的 SPI 协议都有细微差别,配置更为复杂。
梦开始的地方 —— 四线全双工 SPI
四线全双工 SPI 为最常见的 SPI 协议,四线分别为:
常见缩写 | 全称 | 方向 | 描述 |
CS/NSS/SS | Chip Select/Not Slave Select/Slave Select | 主 -> 从 | 片选,通常低电平有效 |
SCLK/SCK | Serial Clock | 主 -> 从 | 同步时钟信号 |
MOSI | Master Out, Slave In | 主 -> 从 | 主机数据信号 |
MISO | Master In, Slave Out | 从 -> 主 | 从机数据信号 |
MOSI、MISO 无需像串口那样交叉连接,多个从机可以配置多个片选。一般可以配置的选项有:
主从模式
SPI 区分主从器件,需要指定主从模式。
SCLK 频率
SCLK 的频率一般取决于从机最大速率和主机频率和可选的分频。
数据长度
数据长度通常为 8 位,但也有些设备并不是 8 位的,通常单片机可以配置位数(例如 STM32F1 可以配置 8、16 位,STM32H7 可以配置 8、16、32 位,ESP8266 可选长度更多),若为单片机不支持的位数,也可以拆分成单片机支持的位数来通信,例如某个外设数据长度为 32 位,但单片机仅支持 16 位,则可以拆分成两个 16 位发送。
时钟极性(CPOL,Clock POLarity)
CPOL 指定 SCLK 在空闲时的电平,CPOL=0 为低电平,CPOL=0 为高电平。
时钟相位(CPHA,Clock PHAse)
CPHA 指定每个数据位相对于 SCLK 的相位,CPOL=0 为立即 / 偶数上升沿输出,奇数上升沿处采样,CPOL=0 为奇数时钟沿输出,偶数时钟沿采样。
常见的组合为 CPOL=0,CPHA=0,有时也会将两个属性组合在一起称之为 SPI 模式(mode)(例如 ESP32),将两者表示为一个数 (CPOL, CPHA),例如 3 就代表着 CPOL=1,CPHA=1。
其他
一些单片机的 SPI 外设还提供了 CRC 校验、将数据分隔为指令、地址、数据等,不再详细展开。
实现
四线 SPI 通常使用硬件外设实现,大部分单片机都会提供 SPI 外设,但也可以使用 GPIO 模拟 SPI 软件实现,但速率通常低于硬件实现的 SPI。
硬件实现
对于普通 SPI 最重要的部分就是移位寄存器,并通过时钟信号更新移位寄存器的内容,因此甚至可以使用 74HC595 这样的串行转并行信号作为一个简单的 SPI 从器件。
尽管使用的是硬件 SPI,但许多时候仍然使用的是软件控制 CS,功能更完全的 SPI 一般最多支持 4 个硬件 CS,普通的 SPI 一般可以支持一个硬件 CS,因此只能使用它片选一个器件,若要片选多个器件就需要使用 GPIO 或者菊花链实现了。
多主机 / 多从机
一主多从
最简单的方式是使用多个 CS 控制,若使用软件 CS 则从机数量几乎可以认为不受限制,例如:
某些器件还支持菊花链,由于 SPI 的核心是移位寄存器,因此菊花链也比较好实现:
多主机
虽然叫多主机,但在任意时刻都只能最多有一个主机,既然如此就需要一个解决冲突的方法,最简单的方法就是将两个主机的 CS 都配置为输入,并使用额外的 CS 通知其他主机是否要接管总线:
速率更快的梦 ——QSPI(Quad SPI)
QSPI 在 SPI 的基础上增加了三条数据线,也就是说在相同始终频率下可以实现几乎四倍的数据传输速率,常用于对速率要求更高的器件,例如 W25Qxx。并且通常单片机会支持地址映射,也就是说可以地址访问外部 QSPI 的 Flash,就像片载的 Flash 一样。
尾声
除此之外,还有许多 SPI 的变体,这也是由于 SPI 是事实标准,各个芯片的实现方式不尽相同,但它又足够简单可靠(无论是电路、外设还是软件),通常单片机实现的 SPI 或 QSPI 外设也都会兼容一部分 SPI 的变体。