引子
串行外设接口(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的变体。