第三章:SPI工作模式——CPOL和CPHA的四种组合

SPI的极性(CPOL)和相位(CPHA)这俩参数,新手看了头大,老手也容易翻车。我这些年调过的SPI设备少说也有几十种,踩过的坑能排成串。

说白了,CPOL决定时钟空闲时的电平。CPHA决定数据在时钟的哪个边沿被采集。两两组合,正好四种模式。

3.1 先搞清楚CPOL和CPHA各管什么事

参数 含义 取值 效果
CPOL 时钟极性 0 空闲时SCLK为低电平
1 空闲时SCLK为高电平
CPHA 时钟相位 0 第一个边沿(上升或下降)采集数据
1 第二个边沿采集数据

CPOL = 0,空闲低。CPOL = 1,空闲高。这个好记。

CPHA = 0,时钟的第一个动作(从空闲跳变到有效)用来锁存。CPHA = 1,时钟的第二个动作(从有效跳变回空闲)用来锁存。

我当年犯过的错

我曾经把一个CPHA=0的从机,配成了CPHA=1,结果数据全是乱的。示波器上波形看着像那么回事,但读出来的字节对不上。后来发现手册里写着“Data is latched on the first edge”,我愣是没当回事。从那以后我再也不敢只看波形猜模式了。

3.2 四种模式一览表

模式 CPOL CPHA 空闲时钟 数据采样边沿 常见从机芯片举例
模式0 0 0 低 上升沿(第一个边沿) 大多数通用SPI Flash、SD卡
模式1 0 1 低 下降沿(第二个边沿) 某些ADC、DAC
模式2 1 0 高 下降沿(第一个边沿) 部分温度传感器
模式3 1 1 高 上升沿(第二个边沿) 很多微控制器内部SPI外设

这里有个规律:模式0和模式3,采样边沿都是上升沿。模式1和模式2,采样边沿都是下降沿。区别就在空闲电平上。

3.3 一张图看懂四种模式

下面这个SVG图把四种模式的时钟和数据关系画出来了。我建议你存下来,写代码之前看一眼。

SPI四种工作模式波形示意图 模式0 (CPOL=0, CPHA=0) SCLK MOSI ← 上升沿采样 模式1 (CPOL=0, CPHA=1) SCLK MOSI ← 下降沿采样 模式2 (CPOL=1, CPHA=0) SCLK MOSI ← 下降沿采样 模式3 (CPOL=1, CPHA=1) SCLK MOSI ← 上升沿采样 图例 SCLK MOSI 采样时刻 空闲电平:模式0/1为低 空闲电平:模式2/3为高

3.4 如何快速确定该用哪个模式

打开从机数据手册,找到时序图那一页。看两个地方:

  • 空闲时SCLK是高还是低 —— 对应CPOL
  • 数据是在第一个边沿变化,还是第二个边沿被采集 —— 对应CPHA

举个例子。你拿一个SPI Flash芯片,手册上写“Data is shifted on the rising edge of SCLK”。如果空闲时SCLK是低,那就是模式0。如果空闲时SCLK是高,那就是模式3。

我个人的习惯

调新板子时,我一般先把主机配成模式0。因为绝大多数器件默认支持模式0。如果通信不正常,我再试着切模式3(都一样是上升沿采样,只是空闲电平不同)。

3.5 代码里怎么配置

不同MCU配置方式不一样,但思路一致。以STM32的HAL库为例:

// SPI句柄初始化
hspi1.Init.CLKPolarity     = SPI_POLARITY_LOW;   // CPOL = 0
hspi1.Init.CLKPhase        = SPI_PHASE_1EDGE;    // CPHA = 0
// 这就是模式0
// 如果你想用模式1(CPOL=0, CPHA=1):
hspi1.Init.CLKPolarity     = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase        = SPI_PHASE_2EDGE;
// 模式2(CPOL=1, CPHA=0):
hspi1.Init.CLKPolarity     = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase        = SPI_PHASE_1EDGE;
// 模式3(CPOL=1, CPHA=1):
hspi1.Init.CLKPolarity     = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase        = SPI_PHASE_2EDGE;

避坑小贴士

我曾经遇到过一款国产温度传感器,手册上写着“支持模式0和模式3”。我试了模式0,能读,但偶尔丢一个字节。换成模式3,稳如老狗。后来查勘误表才发现——芯片内部逻辑对下降沿触发有微小的保持时间裕量问题。所以多试一种模式,有时候能救命。

3.6 用逻辑分析仪判断当前模式

如果你手头有逻辑分析仪(我每次都开),抓一段SCLK和CS的波形,看CS拉低之后第一个时钟跳变的方向:

  • 如果空闲低,第一个跳变是上升沿 → 可能是模式0(CPHA=0)
  • 如果空闲低,第一个跳变是下降沿 → 可能是模式1(CPHA=1)
  • 如果空闲高,第一个跳变是下降沿 → 可能是模式2(CPHA=0)
  • 如果空闲高,第一个跳变是上升沿 → 可能是模式3(CPHA=1)

再看片选释放时SCLK是啥电平:如果和空闲一致,基本就能确认。

嗯,这章就到这。四种模式,说穿了就是自由组合两个只有0/1的开关。关键是要和从机芯片的时序图对上号。调通一次,以后就快了。