4. CPHA=0 与 CPHA=1 的区别:数据采样边沿与建立/保持时间分析

在 SPI 通信中,CPHA(Clock Phase,时钟相位)决定了数据采样时刻相对于时钟边沿的位置。CPHA 与 CPOL 共同定义了四种 SPI 模式,但 CPHA 本身直接决定了数据是在时钟的第一个跳变沿采样,还是在第二个跳变沿采样。这一差异对从设备的建立时间(Setup Time)和保持时间(Hold Time)要求有显著影响。

4.1 核心概念:第一个跳变沿 vs 第二个跳变沿

CPHA 的定义基于一个完整的 SPI 时钟周期(一个数据位传输周期):

  • CPHA=0:数据在时钟的第一个跳变沿被采样(即数据采样边沿)。
  • CPHA=1:数据在时钟的第二个跳变沿被采样。

这里的“第一个”和“第二个”是相对于每个数据位的传输周期而言的。无论 CPOL 是 0 还是 1,CPHA 的定义始终不变。

关键记忆法: CPHA=0 时,采样边沿是时钟的第一个边沿(上升或下降取决于 CPOL);CPHA=1 时,采样边沿是时钟的第二个边沿。CPHA 的数字越小,采样发生得越早。

4.2 CPHA=0 与 CPHA=1 的时序对比表

参数 CPHA=0 CPHA=1
采样边沿 第一个跳变沿 第二个跳变沿
数据变化边沿 第二个跳变沿(或 CS 有效后立即变化) 第一个跳变沿
CS 有效到第一个采样点的空闲时间 半个时钟周期(用于数据建立) 一个完整时钟周期(用于数据建立)
典型应用场景 低速设备、对建立时间要求宽松的设备 高速设备、需要更长建立时间的设备
数据输出延迟 从 CS 有效或第二个边沿开始 从第一个边沿开始

4.3 建立时间与保持时间分析

建立时间(tsu)和保持时间(th)是从设备正确采样数据的必要条件。CPHA 的选择直接影响这两个时间窗口的分配。

4.3.1 CPHA=0 时的时序窗口

  • 建立时间窗口:从 CS 有效(或前一位数据变化)到第一个采样边沿之间的时间。在 CPHA=0 模式下,这个窗口为 半个时钟周期(T/2)。
  • 保持时间窗口:从第一个采样边沿到第二个数据变化边沿之间的时间,同样为 半个时钟周期(T/2)。
  • 特点:建立时间和保持时间均等,各占半个周期。对于低速时钟,这个窗口足够宽;但随着时钟频率提高,T/2 会缩短,可能无法满足从设备的时序要求。

4.3.2 CPHA=1 时的时序窗口

  • 建立时间窗口:从第一个数据变化边沿到第二个采样边沿之间的时间,为 一个完整时钟周期(T)。
  • 保持时间窗口:从第二个采样边沿到下一个数据变化边沿之间的时间,为 零或极小(取决于从设备实现)。
  • 特点:建立时间窗口加倍,非常适合需要较长建立时间的高速从设备。但保持时间窗口几乎为零,对从设备的数据保持能力要求更高。
工程经验: 当调试 SPI 通信失败时,如果怀疑是时序裕量不足,可以尝试将 CPHA 从 0 改为 1(保持 CPOL 不变)。这会将建立时间从 T/2 增加到 T,通常能解决因建立时间不足导致的采样错误。

4.4 内联 SVG:CPHA=0 与 CPHA=1 时序对比图

下图展示了在 CPOL=0(空闲低电平)条件下,CPHA=0 和 CPHA=1 的时序差异。蓝色箭头表示数据变化边沿,红色箭头表示数据采样边沿。

CPHA=0 与 CPHA=1 时序对比(CPOL=0) 数据变化边沿 数据采样边沿 CPHA=0 CS SCLK 数据变化 采样 建立时间 = T/2 CPHA=1 CS SCLK 数据变化 采样 建立时间 = T(完整周期)

4.5 实际调试中的选择策略

在驱动适配过程中,选择 CPHA=0 还是 CPHA=1 通常取决于从设备的数据手册。以下是一些实用的调试策略:

  1. 查阅数据手册:从设备数据手册中会明确给出支持的 SPI 模式(Mode 0~3)。Mode 0 对应 CPOL=0, CPHA=0;Mode 1 对应 CPOL=0, CPHA=1;以此类推。
  2. 默认尝试 Mode 0:大多数 SPI 设备默认支持 Mode 0(CPOL=0, CPHA=0)。如果通信不稳定,再尝试 Mode 1(CPOL=0, CPHA=1)。
  3. 使用逻辑分析仪验证:通过逻辑分析仪捕获实际波形,观察数据变化边沿与采样边沿的相对位置,确认是否符合预期。
  4. 调整时钟频率:如果 CPHA=0 时建立时间不足(T/2 过小),可以降低 SPI 时钟频率以增大 T,或者切换到 CPHA=1 以获得完整的 T 建立时间。
常见陷阱: 有些从设备的数据手册中描述的“采样边沿”可能使用“上升沿”或“下降沿”而非 CPHA 编号。务必结合 CPOL 一起理解。例如,“在时钟上升沿采样”并不直接等于 CPHA=0,还需要知道 CPOL 的值才能确定是第一个还是第二个上升沿。

4.6 代码示例:在 Linux 设备树中配置 CPHA

在 Linux 内核中,SPI 设备的 CPHA 参数通过设备树或板级代码配置。以下是一个设备树片段示例:

/* 设备树中配置 SPI 从设备 */
&spi0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_spi0>>;

    spidev@0 {
        compatible = "spidev";
        reg = <0>;
        spi-max-frequency = <10000000>;  /* 10 MHz */
        spi-cpol = <0>;                  /* CPOL = 0 */
        spi-cpha = <1>;                  /* CPHA = 1 → Mode 1 */
    };
};

在驱动代码中,也可以通过 SPI 控制器接口动态设置模式:

/* 驱动代码中设置 SPI 模式 */
struct spi_device *spi;
u8 mode = SPI_MODE_1;  /* CPOL=0, CPHA=1 */

spi->mode = mode;
spi_setup(spi);  /* 应用配置 */

4.7 本章小结

  • CPHA=0:采样在第一个跳变沿,建立时间和保持时间各占 T/2,适合低速或对时序要求不高的设备。
  • CPHA=1:采样在第二个跳变沿,建立时间为完整 T,保持时间极短,适合高速或需要长建立时间的设备。
  • 调试建议:优先参考数据手册,使用逻辑分析仪验证波形,必要时通过切换 CPHA 或降低时钟频率来满足时序裕量。