2. SPI 时序与模式:CPOL 与 CPHA 详解

SPI(Serial Peripheral Interface)是一种同步、全双工、主从结构的串行通信协议。其核心在于主设备通过 SCLK(串行时钟) 控制数据传输的节奏,而 CPOL(时钟极性) 和 CPHA(时钟相位) 则决定了 SCLK 在空闲状态下的电平以及数据采样/切换的具体时刻。理解这两个参数是正确配置 SPI Flash 驱动的基础。

2.1 CPOL 与 CPHA 核心概念

参数 全称 定义 取值
CPOL Clock Polarity 决定 SCLK 在空闲状态(无数据传输时)的电平。 0:空闲为低电平
1:空闲为高电平
CPHA Clock Phase 决定数据在 SCLK 的哪个边沿被采样(捕获)。 0:在第一个边沿采样
1:在第二个边沿采样
记忆技巧: CPOL 决定“空闲时”的时钟样子;CPHA 决定“哪个边沿”抓数据。两者组合形成 4 种 SPI 模式。

2.2 SPI 四种模式(Mode 0/1/2/3)

CPOL 和 CPHA 的 4 种组合对应 4 种标准 SPI 模式。绝大多数 SPI Flash 器件默认支持 Mode 0 和 Mode 3,但驱动开发时必须根据数据手册明确配置。

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

2.3 时序图详解:Mode 0 与 Mode 3

下面通过内联 SVG 时序图直观展示最常用的 Mode 0 和 Mode 3 的波形差异。图中包含 SCLK、MOSI(主出从入)和 MISO(主入从出)信号。

SPI Mode 0 与 Mode 3 时序对比图 SPI Mode 0 (CPOL=0, CPHA=0) 与 Mode 3 (CPOL=1, CPHA=1) 时序对比 Mode 0: SCLK 采样(上升沿) MOSI Bit 7 Bit 6 Bit 5 Bit 4 MISO Bit 7 Bit 6 Bit 5 Bit 4 Mode 3: SCLK 采样(上升沿) MOSI Bit 7 Bit 6 Bit 5 Bit 4 MISO Bit 7 Bit 6 Bit 5 Bit 4 关键差异说明 • Mode 0:空闲时 SCLK = 低电平 数据在上升沿采样,下降沿切换。 • Mode 3:空闲时 SCLK = 高电平 数据在上升沿采样,下降沿切换。 • 两种模式采样边沿相同(上升沿), 但空闲电平相反。 • 多数 SPI Flash 同时支持 Mode 0 和 Mode 3, 驱动配置时需与从设备匹配。

2.4 时钟极性与相位配置实战

在固件开发中,配置 SPI 接口的 CPOL 和 CPHA 通常通过 MCU 的 SPI 控制寄存器完成。以下以 STM32 系列 MCU 为例,展示如何配置 SPI 模式。

/* STM32 SPI 模式配置示例 */
SPI_HandleTypeDef hspi1;

void MX_SPI1_Init(void)
{
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;          // 主模式
    hspi1.Init.Direction = SPI_DIRECTION_2LINES; // 全双工
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;     // 8 位数据
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;   // CPOL = 0
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;       // CPHA = 0
    hspi1.Init.NSS = SPI_NSS_SOFT;               // 软件片选
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;      // MSB 先行
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 10;

    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    {
        // 初始化错误处理
        Error_Handler();
    }
}
配置要点:
  • CPOL = 0 对应 SPI_POLARITY_LOW;CPOL = 1 对应 SPI_POLARITY_HIGH。
  • CPHA = 0 对应 SPI_PHASE_1EDGE(第一个边沿采样);CPHA = 1 对应 SPI_PHASE_2EDGE(第二个边沿采样)。
  • 配置前务必查阅 SPI Flash 数据手册的“SPI Mode”章节,确认支持的时钟模式。

2.5 常见配置错误与排查

错误现象 可能原因 排查方法
通信无响应,MISO 始终为高阻 CPOL/CPHA 与 Flash 不匹配 用逻辑分析仪抓取 SCLK 和 CS 波形,对比数据手册时序图
数据错位(如读回 0xAA 变成 0x55) CPHA 配置错误,导致采样边沿偏移 检查 CPHA 是否与 Flash 要求的相位一致
偶尔通信成功,但高温下失败 时钟极性导致建立/保持时间余量不足 尝试切换 Mode 0 和 Mode 3,观察稳定性
避坑指南: 部分国产 SPI Flash 芯片对时序要求较严格,建议在驱动初始化时增加模式探测流程:先尝试 Mode 0,若读 ID 失败则切换 Mode 3。切勿假设所有 Flash 都默认工作在 Mode 0。

2.6 模式选择决策流程

下面通过 SVG 流程图展示在实际驱动开发中如何选择 SPI 模式。

SPI 模式选择决策流程 SPI 模式选择决策流程 开始配置 SPI 查阅 Flash 数据手册支持的 SPI 模式 手册明确指定 模式? 是 按手册配置 CPOL/CPHA 否 尝试 Mode 0 读 ID 读 ID 成功? 是 使用 Mode 0 完成配置 否 尝试 Mode 3 读 ID 成功? 是 使用 Mode 3 完成配置 否 检查硬件连接或 Flash 型号

2.7 本章小结

  • CPOL 决定空闲时钟电平,CPHA 决定数据采样边沿。
  • 四种 SPI 模式(Mode 0~3)由 CPOL 和 CPHA 组合而成。
  • 实际开发中 Mode 0 和 Mode 3 最为常用,两者采样边沿相同,仅空闲电平不同。
  • 配置时务必以 SPI Flash 数据手册为准,必要时通过读 ID 进行模式探测。
  • 使用逻辑分析仪抓取波形是排查时序问题的最有效手段。