2、SPI物理层与时序:CPOL时钟极性、CPHA时钟相位详解、4种工作模式(Mode 0-3)波形分析

SPI 这个协议,说白了就是四根线的事儿。很多刚入行的朋友觉得它简单,不就是 SCK、MOSI、MISO、CS 嘛。但真到了调驱动、对波形的时候,CPOL 和 CPHA 这两个参数经常把人绕晕。

我记得有一次帮同事排查一个 LCD 屏显示花屏的问题。代码逻辑看了三遍,寄存器配置也检查了,就是不对。最后拿示波器一抓,发现是 SPI 模式配错了。主设备用的是 Mode 0,从设备却工作在 Mode 3。时钟边沿对不上,数据全偏了一位。从那以后,我每次写 SPI 驱动,第一件事就是确认主从设备的模式是否一致。

2.1 物理层:四根线各司其职

先快速过一下物理层。SPI 是同步、全双工的串行接口。主设备负责产生时钟,从设备被动响应。

信号线 全称 方向(主设备视角) 作用
SCK Serial Clock 输出 由主设备产生,决定数据传输速率
MOSI Master Out Slave In 输出 主设备发送数据给从设备
MISO Master In Slave Out 输入 从设备发送数据给主设备
CS Chip Select 输出 片选信号,低电平有效,选中目标从设备

这里有个细节我提一下:CS 信号在大多数应用中都是低电平有效。但有些特殊的传感器或者老式芯片,可能会用高电平选通。写驱动前一定要看数据手册,别想当然。

2.2 CPOL 和 CPHA:时钟的「脾气」

这两个参数决定了时钟信号在空闲时的状态,以及数据在哪个边沿被采样。

  • CPOL(Clock Polarity):时钟极性。它定义的是 SCK 在空闲状态(CS 无效时)的电平。
    • CPOL = 0:空闲时 SCK 为低电平。
    • CPOL = 1:空闲时 SCK 为高电平。
  • CPHA(Clock Phase):时钟相位。它定义的是数据在哪个时钟边沿被采样。
    • CPHA = 0:在 SCK 的第一个边沿(上升沿或下降沿)采样数据。
    • CPHA = 1:在 SCK 的第二个边沿采样数据。

你想想看,CPOL 决定了时钟的「起始姿势」,CPHA 决定了数据采样的「时机」。这两个组合起来,就是四种工作模式。

核心记忆法:

CPHA = 0 时,数据在第一个边沿被锁存。此时 MOSI/MISO 上的数据会在 SCK 第一个边沿之前就准备好。

CPHA = 1 时,数据在第二个边沿被锁存。数据会在第一个边沿之后才更新。

2.3 四种工作模式(Mode 0 - 3)

四种模式其实就是 CPOL 和 CPHA 的排列组合。我习惯用一张表来记:

模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据输出边沿
Mode 0 0 0 低电平 上升沿(第一个边沿) 下降沿
Mode 1 0 1 低电平 下降沿(第二个边沿) 上升沿
Mode 2 1 0 高电平 下降沿(第一个边沿) 上升沿
Mode 3 1 1 高电平 上升沿(第二个边沿) 下降沿

嗯,这里要注意:Mode 0 和 Mode 3 是最常用的两种模式。很多 Flash 芯片、SD 卡默认都支持 Mode 0。而一些无线射频芯片,比如 nRF24L01,默认工作在 Mode 0,但也可以配置为 Mode 3。

2.4 波形分析:眼见为实

光看表格不够直观。我画了一张四种模式的波形对比图,你一看就明白。

SPI 四种工作模式波形对比 Mode 0 (CPOL=0, CPHA=0) SCK MOSI D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 ↑采样 Mode 1 (CPOL=0, CPHA=1) SCK MOSI D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 ↑采样 Mode 2 (CPOL=1, CPHA=0) SCK MOSI D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 ↑采样 Mode 3 (CPOL=1, CPHA=1) SCK MOSI D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 D3 D2 D1 D0 D7 D6 D5 D4 ↑采样 数据有效 采样点

从波形上可以清楚看到:

  • Mode 0:SCK 空闲为低,在上升沿采样数据。这是最常用的模式,很多 MCU 的 SPI 外设默认就是这个配置。
  • Mode 1:SCK 空闲为低,在下降沿采样数据。数据在上升沿更新。
  • Mode 2:SCK 空闲为高,在下降沿采样数据。数据在上升沿更新。
  • Mode 3:SCK 空闲为高,在上升沿采样数据。数据在下降沿更新。

个人经验: 我习惯在驱动初始化时,先读从设备数据手册里的时序图。手册上通常会标注出数据是在 SCK 的哪个边沿被锁存。如果手册上画的是「数据在 SCK 上升沿被采样」,那就对应 CPHA=0(第一个边沿)。如果画的是「数据在 SCK 下降沿被采样」,那就对应 CPHA=1(第二个边沿)。

2.5 避坑指南:模式不匹配的后果

我曾经在一个项目里,把 STM32 的 SPI 配成了 Mode 0,但外接的 ADC 芯片要求 Mode 2。结果就是:数据读出来全是乱的,偶尔对一次,大部分时间错位。

为什么会这样?因为主设备在上升沿发送数据,从设备却在下降沿采样。主设备以为数据已经送出去了,从设备却还没准备好。两边节奏对不上,数据就串位了。

重要提醒:

  • 主设备和从设备的 SPI 模式必须一致,否则通信会失败。
  • 同一个 SPI 总线上挂载多个从设备时,每个从设备可以有不同的模式。但每次切换从设备时,主设备需要重新配置模式。
  • 有些 MCU 的 SPI 外设支持「模式自动切换」,但我不建议依赖这个功能。手动配置更可靠。

2.6 速率与模式的关系

SPI 的速率由 SCK 的频率决定。但模式会影响最高可靠速率吗?

理论上,四种模式对速率没有直接影响。但在实际布线中,Mode 0 和 Mode 3 因为采样边沿和数据边沿的间隔更均匀,抗干扰能力稍强一些。我个人在高速 SPI(比如超过 20 MHz)时,优先选择 Mode 0 或 Mode 3。

另外,CPHA=0 的模式下,数据在第一个边沿之前就必须准备好。这意味着从设备需要更快的响应时间。如果从设备比较慢,可能会出现建立时间不足的问题。这时候可以适当降低时钟频率,或者改用 CPHA=1 的模式。

总结一下:

CPOL 和 CPHA 决定了 SPI 的「握手方式」。理解它们的关键在于: