一、SPI是什么?
SPI(Serial Peripheral Interface)是一种全双工、主从架构的同步串行通信协议。核心物理模型是:将主设备和从设备内的两个移位寄存器通过时钟线连接在一起。每个时钟脉冲到来时,两个移位寄存器同时向前移动一位——主设备移出一位进入从设备,从设备也移出一位进入主设备。八个时钟脉冲结束后,两个设备的寄存器内容就完全互换了。因此,SPI 的本质上是一个极简的移位寄存器数据交换链路。
二、为什么需要SPI?
在一个电路板上,不同的芯片之间需要交换数据,SPI是实现这类板内短距离通信的方案之一。SPI具有速度快(全双工),硬件成本低(只用移位寄存器和少量控制逻辑),协议灵活(数据字长,时钟频率,采样边沿都可以配置)的特点。
三、SPI怎么工作?
3.1 四根信号线——CS/SCK/MOSI/MISO
用一个故事来理解:在一个被围墙隔开的王国里,国王在城堡内,骑士在围墙外。他们只能通过四根绳子来传递信息。国王需要给骑士下达命令,骑士需要接给国王反馈城墙外的情况。如果国王和骑士想要正常沟通,那他们就必须制定一套规则。
绳子一:选人绳(CS,Chip Select)
围墙外有很多骑士,国王必须先决定对谁说话。他选中某个骑士时,就把属于那个骑士的选人绳绷紧拉直;没选中的,绳子就是松的。
绳子二:节拍绳(SCK,Serial Clock)
国王发的消息只有 0 和 1(绳子松或紧)。如果只用一根数据绳,国王发送的消息是01,那就是一松一紧,骑士可以正确理解国王的命令。但如果国王发送的是00,那绳子就一直松着,骑士没法判断这到底是"一个很长的0"还是"两个连续的0"。即只靠一根数据绳,没法区分"连续两个相同的状态"。
于是如果他们约定了一根节拍绳:国王每将节拍绳拉紧一下,就在数据绳上放一个新数字;骑士只在节拍绳拉紧的那一瞬间去识别这根数据绳的状态。
绳子三:国王的传声筒绳(MOSI,Master Out Slave In)
专门用于国王向骑士传递命令。方向固定:只能国王发,骑士收。国王把命令(比如“停止进攻”)转换为只有双方能懂的比特串,然后跟着节拍绳的节拍,一位一位地推过去。
绳子四:骑士的传声筒绳(MISO,Master In Slave Out)
骑士也需要把城外看到的情报报告给国王,这根绳子就是骑士专用的回话通道。同样,只能骑士发,国王收。在节拍绳每拉紧一下的瞬间,国王在 MOSI 上放一个比特给骑士,同时骑士也在 MISO 上放一个比特给国王。两人各说各的,互不冲突。
注意:骑士推出去的数字,并不是对国王“当前正在说的这句话”的回答,而是骑士早就提前准备好要报告的情报。等国王把整条命令发完,骑士也把一个完整的情报同时塞回了国王手里。
因为有两条独立的传声筒绳(MOSI和MISO),发命令和收情报是同时完成的——国王不需要等自己说完再听,骑士也不需要等国王说完再讲。这种特性就叫“全双工”。SPI的全双工不是两个人聊天,而是两个人同时给对方传递信息。
3.2 四线总结
| 信号线 | 方向 | 功能 |
|---|---|---|
| SCK | 主→从 | 时钟线,由主设备产生,为通信提供节拍 |
| MOSI | 主→从 | 主设备发数据,从设备收数据 |
| MISO | 从→主 | 从设备发数据,主设备收数据 |
| CS / SS | 主→从 | 片选线 |
3.3、如何对齐采样时刻——CPOL 和 CPHA
3.3.1 两个问题
已经知道SCK起到一个节拍器的作用,此时存在两个问题:
Q1:国王和骑士是在SCK绳拉紧的时候读指令还是SCK绳松着的时候读数据?
错误场景1:国王在绳子拉紧后发数据,骑士在国王松绳子后读数据。
错误场景2:国王在松绳子后发数据,骑士在国王拉紧后读数据。
Q2:国王不发指令时,SCK绳默认是拉紧还是松的?
如果国王平时一直拉紧绳子(默认高电平),那他要发数据的时候,第一个动作就是松绳子;如果国王平时一松着绳子(默认低电平),那第一个动作是拉绳子拉紧。若国王习惯默认是低电平,骑士认为是默认是高电平,国王一拉紧绳子,骑士认为国王恢复到了自己认为的默认状态,就不管;但国王一松绳子,骑士误以为国王要发指令,就准备开始工作。国王和骑士各自觉得自己做得对,但读出来的全是错位、遗漏、误判的数据。
3.3.2 CPOL和CPHA
CPHA(相位):决定是在SCK绳变松的时候读取数据,还是在拉紧的时候读数据——解决Q1;
CPOL(极性):决定没发数据时,SCK绳是松的还是拉紧的——解决Q2;
因此 SPI 定义了两个参数:
CPOL(Clock Polarity,时钟极性):决定空闲时 SCK 的电平。
CPOL = 0:空闲时 SCK 为低电平。
CPOL = 1:空闲时 SCK 为高电平。
CPHA(Clock Phase,时钟相位):决定数据在第几个时钟边沿被采样。
CPHA = 0:在第一个时钟边沿采样。
CPHA = 1:在第二个时钟边沿采样。
两个参数互相配合,产生出 4 种标准工作模式,主设备和从设备必须配置相同的模式才能正常通信。
| SPI 模式 | CPOL | CPHA | 采样边沿(锁存数据) | 更新边沿(输出新数据) |
|---|---|---|---|---|
| 模式 0 | 0 | 0 | SCK 上升沿 | SCK 下降沿 |
| 模式 1 | 0 | 1 | SCK 下降沿 | SCK 上升沿 |
| 模式 2 | 1 | 0 | SCK 下降沿 | SCK 上升沿 |
| 模式 3 | 1 | 1 | SCK 上升沿 | SCK 下降沿 |
3.3.3 以模式1为例分析波形
模式1:CPOL = 0,CPHA = 1
上图中SCK空闲时为低电平,对应CPOL=0;CPHA=1指的是从SCK的第2个边沿开始采样;结合CPOL=0和CPHA=1可知在下降沿处开始采样。此时所有输出更新都是在上升沿,所有数据采样都是在下降沿;对应图中:虚线代表上升沿输出,点线代表下降沿采样。
时序流程单 bit 拆解(CPOL=0 CPHA=1)
(1)初始:SCK=0 空闲时下降沿
(2)SCK↑上升沿(第 1 边沿):
主机移位寄存器 → 更新 MOSI
从机移位寄存器 → 更新 MISO
(3)SCK 高电平维持一段时间:MOSI/MISO 数据稳定
(4)SCK↓下降沿(第 2 边沿)
从机锁存 MOSI bit
主机锁存 MISO bit
(5)SCK 回到低,完成 1bit,循环下一位
四、SPI支持的连接方式
SPI的常见的连接方式有2种:一主一从,一主多从
4.1 一主一从
连接:4 根信号线(SCK、MOSI、MISO、CS)直接一对一连接。
4.2 一主多从
一主多从有两种连接方式:标准模式(独立片选线)和菊花链模式
4.2.1 标准模式(独立片选线)
(1)连接:SCK、MOSI、MISO 三根线并联共享,CS 线每个从设备一根;
(2)规则:
任意时刻,有且只有 1 个从设备的 CS 被选中。
未被选中的从设备,其 MISO 引脚必须处于高阻态(不干扰总线)。
主设备选谁,谁就应答;其他从设备不作反应。
(3)优缺点:
优点:逻辑简单,各从设备可以独立工作在不同的模式和速率。
缺点:每增加一个从设备,每增加一个从设备,主设备就需要多一根 GPIO(片选脚)。
4.2.2 菊花链模式(Daisy Chain)
(1)连接方式:所有从设备共用一根 CS 线,数据线串联——主 MOSI → 从设备 1 输入 → 从设备 1 输出 → 从设备 2 输入 → … → 最后一个从设备输出 → 主 MISO
(2)规则:所有从设备同时被同一根 CS 选中,数据像流水线一样依次流经每个设备。
(3)优缺点:
优点:只用 1 根 CS,节省主设备引脚;适合需要同步控制多个相同芯片的场合。
缺点:所有设备必须同时工作,模式必须一致;数据延迟较长(要通过一条链);一个设备出问题,整个链就断了。
五、SPI的优点和缺点
5.1 优点
(1)全双工,速度快:MOSI 和 MISO 两根数据线独立,主发从收和从发主收可以同时进行,同等时钟频率下,有效吞吐量几乎是半双工协议的两倍。
(2)协议简单,硬件实现成本极低。
(3) 时钟灵活,没有固定速率上限,时钟完全由主设备产生,从设备无条件跟随。
(4)支持任意字长:数据不一定是 8 位,可以是 9 位、12 位、16 位等。
(5) 无硬件地址限制,天然支持“广播”:通过物理 CS 线选择设备,不需要在帧内嵌入地址字节。如果同时拉低多个 CS,还可以一次性向多个从设备发送相同数据(广播)。
5.2 缺点
(1) 引脚消耗大:用物理片选代替地址字段,每增加一个从设备就要多一根 CS 线。菊花链能省 CS,但失去了独立控制能力。
(2)没有标准化的流控和应答机制:主设备发送数据后无法知道从设备是否正确接收,也不知道从设备是否忙。
(3)无硬件级别的错误检测:没有奇偶校验位,没有强制 CRC。数据在传输中若发生位翻转,硬件层面完全无法察觉。
(4)传输距离短,抗干扰能力弱:信号为单端高速数字电平,没有差分或复杂的噪声容限设计,通常只适合同一块电路板内的短距离通信。
(6)从设备永远被动:从设备不能主动发起通信。当从设备有紧急数据(如传感器报警)时,只能等主设备发起下一次传输时“搭车”上报,或者额外接一根独立的中断引起来通知主设备。
5.3 SPI 的取舍理解
| 设计取舍 | 在「国王与骑士」故事中理解 | 这样做换来的好处 | 这样做付出的代价 |
|---|---|---|---|
| 放弃地址字段 | 国王不喊“3号骑士听令!”,而是直接拉一下属于3号骑士的专属选人绳。骑士根本不用知道自己编号。 | 协议帧不含任何地址开销,从设备仅需移位寄存器,硬件实现极简; 通信效率高,纯数据直达。 | 必须为每个从设备分配独立的片选线(CS),导致主设备引脚数量随从设备增多而线性增加,限制系统可扩展性。 |
| 放弃应答机制 | 国王说完一句话,不等骑士回答“收到”,马上说下一句。同时骑士也在自顾自情报上报,两人互不打断。 | 不存在应答等待周期,时钟频率可连续拉满; 全双工通信完全不受从机响应速度制约,吞吐量最大化。 | 主设备无法感知从设备是否接收成功或正忙碌;缺乏底层流控和错误通知,可靠性依赖上层协议。 |
| 放弃硬件校验 | 两人传递的消息不附加任何防伪印章或校验码,只传原话。 | 每个时钟沿均传输有效载荷位,无校验位或 CRC 带来的带宽开销; 移位寄存器电路最简,无额外逻辑延迟。 | 物理层无任何错误检测能力,位翻转等传输错误无法被发现,数据完整性必须由应用层自行保证(如软件 CRC、重传)。 |
六、适用场景与替代方案
6.1 适用SPI的应用场景
(1)对速度要求高的器件;
(2)板上设备数量不多,且MCU有足够的GPIO;
(3)需要全双工、低延迟、恒定传输间隔的场合;
6.2 不适合SPI的应用场景
(1)引脚紧张且从设备众多 → 改用 I²C(2 线,带地址,可挂上百个设备);
(2)需要米级以上长距离通信 → 改用 RS-485、CAN 等差分总线;
(3)从设备需要主动报告事件,又不想额外加中断线 → I²C 或异步串口可能更合适;
(4)要求热插拔、硬件仲裁、复杂错误恢复 → 使用 I²C、USB 等带完善协议栈的总线;
七、实际工作中对SPI分析需要注意的点
(1)主从模式:芯片支持主模式还是从模式,或者两者均可?
(2)时钟模式:支持哪几种 CPOL/CPHA 组合?主从必须一致。
(3)最高频率:主设备能产生、从设备能容忍的最高 SCK 频率是多少?以两者中低的为准。
(4)数据格式:字长多少位?先发最高位(MSB)还是最低位(LSB)?
(5)CS 管理:硬件自动 CS 还是软件 GPIO 控制?从设备是否要求每帧后 CS 必须拉高?
(6)电气特性:引脚输入/输出电平标准、是否 5V 容忍、MISO 未选中时是否真正高阻。
(7)可靠性补偿:由于 SPI 无硬件应答和校验,应用中通常需要增加软件 CRC 校验、通信超时处理等机制来保证数据可靠。