SPI 协议层
SPI 协议层详解
一次完整传输的流程
- 主机拉低目标从机的 CS,选中该从机;
- 主机在 SCK 上产生时钟,同时从 MOSI 移出数据、从 MISO 移入数据——每个时钟周期交换 1 bit,发送与接收同时进行(全双工);
- 传完约定的位数后,主机拉高 CS,结束本次传输。
SPI 没有固定的帧格式:数据位数(通常 8 bit,也可 16/24/32)由器件手册约定,没有起始位/停止位/应答位——这是它与 UART、I2C 协议层最大的区别。
时钟极性与时钟相位
- 时钟极性(CPOL):决定 SCK 空闲时的电平。CPOL=0 空闲低,CPOL=1 空闲高;
- 时钟相位(CPHA):决定数据在第1个跳变沿采样(CPHA=0)还是第2个跳变沿采样(CPHA=1)。
SPI 传输模式
CPOL 与 CPHA 组合出 4 种模式:
| 模式 | CPOL | CPHA | 空闲电平 | 采样沿 | 数据变化沿 |
|---|---|---|---|---|---|
| 模式 0 | 0 | 0 | 低 | 上升沿 | 下降沿 |
| 模式 1 | 0 | 1 | 低 | 下降沿 | 上升沿 |
| 模式 2 | 1 | 0 | 高 | 下降沿 | 上升沿 |
| 模式 3 | 1 | 1 | 高 | 上升沿 | 下降沿 |
记忆规律:采样沿与数据变化沿永远相反。CPOL 决定空闲电平,CPHA=0 用第一个沿采样,CPHA=1 用第二个沿采样。
数据传输时序
模式 0(CPOL=0, CPHA=0,最常用)
空闲 SCK 为低;CS 拉低后,SCK 上升沿采样、下降沿换数据,先发 MSB:
{
signal: [
{ name: "CS", wave: "10........1" },
{ name: "SCK", wave: "0pppppppp." },
{ name: "MOSI", wave: "x33333333x", data: "D7 D6 D5 D4 D3 D2 D1 D0" },
{ name: "MISO", wave: "x33333333x", data: "D7 D6 D5 D4 D3 D2 D1 D0" }
]
}
- MOSI 与 MISO 同时传输:主机每发出 1 bit,也收到从机 1 bit;
- 数据在下降沿变化、上升沿稳定,接收方在上升沿采样最稳。
模式 3(CPOL=1, CPHA=1)
空闲 SCK 为高;CS 拉低后,SCK 上升沿采样、下降沿换数据(与模式 0 采样沿相同,只是空闲电平相反):
{
signal: [
{ name: "CS", wave: "10........1" },
{ name: "SCK", wave: "1nnnnnnnn." },
{ name: "MOSI", wave: "x33333333x", data: "D7 D6 D5 D4 D3 D2 D1 D0" },
{ name: "MISO", wave: "x33333333x", data: "D7 D6 D5 D4 D3 D2 D1 D0" }
]
}
数据有效性总结
- 发送方(主机/从机各自):在数据变化沿更新 MOSI/MISO;
- 接收方:在采样沿锁存数据;
- 只要主机与从机约定同一模式(CPOL/CPHA 一致),两边自然对齐。主机与从机模式不一致时,数据会在错误的边沿被采样——表现为读到移位半个周期的数据或全错。
📌 待补图:模式 1、模式 2 的时序图