SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信接口,用于短距离通信,主要应用在嵌入式系统中。全双工数据传输,通常采用四线制连接方式:MOSI(Master Out Slave In)、MISO(Master In Slave Out)、SCLK(Serial Clock)和SS/CS(Slave Select/Chip Select)。这种简单的主从架构使得多个从设备可以与单个主设备通信。
1.SPI通常为四线制通信方式:
|
SCLK |
时钟信号,由主机提供,决定数据传输的节拍。 |
|
MOSI |
主机输出数据,从机输入数据引脚。 |
|
MISO |
主机输入数据,从机输出数据引脚。 |
|
CS/SS |
片选引脚,主机控制,用于选择当前通信的从机。 |
*只有CS被拉低时 时钟线和数据线的数据才有意义
2.SPI工作模式
SPI存在四种不同的工作模式,这些模式主要区别在于时钟极性和时钟相位的不同组合
|
模式 |
CPOL |
CPHA |
空闲电平 |
采样边沿 |
数据切换边沿 |
使用频率 |
|
Mode0 |
0 |
0 |
低 |
上升沿↑ |
下降沿↓ |
⭐⭐⭐⭐⭐ |
|
Mode1 |
0 |
1 |
低 |
下降沿↓ |
上升沿↑ |
⭐⭐⭐ |
|
Mode2 |
1 |
0 |
高 |
下降沿↓ |
上升沿↑ |
⭐⭐ |
|
Mode3 |
1 |
1 |
高 |
上升沿↑ |
下降沿↓ |
⭐⭐ |
CPOL(Clock Polarity):表示高低电平顺序,叫做极性;CPHA表示第一个/第二个边沿,叫做相位。
CPOL时钟极性选择CPOL=0,SPI总线空闲时,时钟线SCLK为低电平 ;CPOL=1,SPI总线空闲时,时钟线SCLK为高电平。数据的传输是从电平跳变开始的,CPOL控制在数据传输开始前,时钟信号的电平是处于低电平0还是高电平1状态。

SPI是全双工同步传输,每个SCLK时钟脉冲可同时完成1位数据的发送和接收:主机发1bit的同时,也在收1bit,传输 N bit 后,双方交换了 N bit 数据
-
通信以片选线拉低作为起始信号,拉高作为结束信号。
-
主从设备内各有一个移位寄存器,在时钟脉冲驱动下,两个寄存器同步移位,8个时钟周期即可完成1字节数据的双向交换,无需额外的起始位、停止位。
-
数据默认高位(MSB)在前、低位(LSB)在后,也可根据外设需求灵活配置传输顺序。
以使用最多的mode0为例:
-
在SCLK的上升沿时期,MISO接收数据
-
在SCLK的下降沿时期,MOSI发送数据

直白讲就是在每个时钟上升沿来之前要先将下一个周期的数据准备好,通常在测试开发建立SPI读写向量时,会设置时钟信号跳变沿比mosi跳变沿晚一点,数据采样点的位置比时钟信号上沿设置晚一点。
在芯片测试中通常工作模式是固定的,大多数情况不用关心CPOL和CPHA的状态设置,通常规格书中会有类似如图1-2的时序图供参考,根据时序图既可设计出正确的SPI通讯向量和时序设置。

cmd[7:1]是寄存器地址;cmd[0]是寄存器的R/W读写标识(蓝框);cmd[0]=1时表示读;cmd[0]=0表示写。WDATA[7:0]是需要写入寄存器的数据,RDATA[7:0]是寄存器输出的数据。如果只向寄存器中写入数据只需CS/SCLK/MOSI三根线就行,通常在配置寄存器时MISO的状态会在测试向量中设置成固定的电平或低电平,在回读寄存器数据时WDATA[7:0]也会设置成固定的1或0,
在芯片测试规格书中通常寄存器地址有两种写法,一种是将读写位和地址位放一起组成一个字节,另一种是将R/W读写位单独分开只写地址位。比如给地址0010101写数据时可以写成addr=0X15(不包含R/W)也可以写成addr=0X2A (0010 1010 包含R/W);同样读数据时可以写成addr=0X15(不包含R/W),也可以写成addr=0X2B (0010 1011 包含R/W)都是一样的。
比如向地址0x15写0xaa,也可以说是给地址0X2A写0xaa

从地址0x15中读0xaa,也可以说是给地址0X2B写0xaa

在做测试开发时需要格外注意,最好不要把R/W位和7bit地址合起来当一个字节地址理解,否则在读数据时会有实际出的是前一个地址写入的数据的错觉
比如0x00 vs 0x01读写地址不一样,0x01不是"地址1",是"地址0 + R/W位",如果合一起理解会发现"地址差1",但不是"读前一个地址",而是 R/W位占用了最后1个bit,让你误以为地址变了。实际上地址没变,变的只是命令。这个错位感来自全双工时间错位,不是地址错位。
-
SPI协议本身没有内置"读/写"的概念——SPI只是一个bit流传输机制,读写操作是由从机的命令集定义的,不是SPI协议层的。
-
MOSI在地址阶段(上图0X15)发的是当前地址,在数据阶段(上图0Xaa)发的是dummy(空数据)。
-
MISO在地址阶段(上图0X15)回的可能是前一个地址的数据(或dummy),在数据阶段(上图0X15)才回当前地址的数据。
3.多从设备管理
既然SPI被称为总线,那肯定像I2C一样可以支持一个主机带多个从机设备的,SPI本身不带地址机制,靠片选线CS区分从机,主机与各个从机直接共同连接在SCLK、MOSI、MISO上,每个从机单独有一个SS/CS片选与主机连接,通信时,主机通过拉低对应从机的SS/CS来选择通信对象,除此之外还有一个菊花链的拓扑连接方式


菊花链:在数字通信世界中,设备信号(总线或中断信号)以串行的方式从一个设备依次传到下一个设备,不断循环直到数据到达目标设备的方式。
菊花链从机只需要主机提供一个从机选择信号,因为这种配置要求所有从机同时启用,以确保数据不间断地流经该链路中的所有移位寄存器。典型应用是工业I/O模块中的级联多通道输入串行器与输出驱动器。
4.SPI / I2C/UART 对比
| 同步方式 |
✅同步(SCLK) |
✅同步(SCL) |
❌异步(无时钟线,靠波特率约定) |
| 通信方向 |
全双工 |
半双工 |
全双工 |
| 信号线数量 |
4根:SCLK + MOSI + MISO + CS |
2根:SCL + SDA |
2根:TX + RX(+GND) |
| 主从架构 |
单主多从 |
多主多从(有仲裁机制) |
点对点,无主从概念 |
| 寻址方式 |
硬件片选线(CS拉低选中) |
软件地址帧(7位/10位地址) |
无寻址,直接收发 |
| 应答机制 |
❌ 无ACK/NACK |
✅ 有ACK/NACK |
✅ 有校验位(奇偶校验,可选) |
| 数据帧格式 |
无帧头,连续比特流 |
起始位 + 地址 + R/W + ACK + 数据 + ACK + 停止位 |
起始位(1bit) + 数据(5~9bit) + 校验位(可选) + 停止位(1~2bit) |
| 时钟极性/相位 |
4种模式可调(CPOL+ CPHA) |
固定 |
不适用 |
| 典型速率 |
10 ~ 50+ Mbps(常用10~20Mbps) |
100Kbps/400Kbps/ 3.4Mbps |
9600 ~ 115200 bps(极限~1Mbps) |
| 速率排序 | 最快 |
中等 |
最慢 |
| 传输距离 |
板内短距离(< 0.2m,高频更短) |
板内短距离(< 0.5m) |
较远(TTL级~1m,RS485可达1200m) |
| 抗干扰能力 |
一般(推挽输出,无上拉) |
较弱(开漏输出,依赖上拉电阻,总线电容≤400pF) |
一般(单端信号) |
| GPIO占用 |
每增加1个从机 +1根CS线 |
不随设备数增加(地址寻址,最多127个) |
固定2根 |
| 协议复杂度 |
⭐简单(无应答、无地址) |
⭐⭐⭐较复杂(起始/停止/应答/仲裁/时钟伸展) |
⭐⭐中等(波特率+数据位+校验+停止位需匹配) |
| 典型应用 |
Flash(W25Q)、SD卡、OLED屏、ADC/DAC、以太网PHY |
EEPROM(AT24C)、RTC、温湿度传感器(BME280)、IO扩展(PCF8574) |
蓝牙模块、GPS、调试打印、RS485工业通信 |
| 一句话总结 | 快、简单、费线 | 省线、灵活、中等速度 | 通用、远距离、最慢 |
*使用注意事项
模式必须匹配:主从设备CPOL/CPHA必须一致,否则采样错位导致通信失败
CS时序严格:CS提前拉低、延后拉高,否则首/末字节丢失
无硬件应答:无法确认数据是否接收成功,建议软件加CRC校验
MISO高阻态:CS无效时从设备MISO必须置高阻,否则总线冲突
速率受限于最慢设备:多从机共享总线时,SCLK频率按最慢从机设定
关键约束:CS必须在SCLK启动之前拉低,在SCLK停止之后拉高多字节传输时CS需全程保持低电平,不可中途释放
SPI协议本身无强制标准,不同厂家芯片可能有细微差异,务必以具体芯片数据手册为准,通常芯片datasheet中都会有其相应的时序图可以参考。



