SPI 协议层

SPI 协议层详解

一次完整传输的流程

  1. 主机拉低目标从机的 CS,选中该从机;
  2. 主机在 SCK 上产生时钟,同时从 MOSI 移出数据、从 MISO 移入数据——每个时钟周期交换 1 bit,发送与接收同时进行(全双工);
  3. 传完约定的位数后,主机拉高 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 的时序图