4. SPI 基础配置:时钟极性、时钟相位、数据帧格式与波特率

SPI 通信的可靠性高度依赖于主从设备之间的时序参数完全一致。在配置 MCU 的 SPI 外设时,必须正确设置 时钟极性 (CPOL)、时钟相位 (CPHA)、数据帧格式 和 波特率 四个核心参数。任何一项配置错误,都会导致数据移位错位或通信失败。

4.1 时钟极性 (CPOL) 与时钟相位 (CPHA)

CPOL 和 CPHA 共同决定了 SPI 总线上时钟信号 (SCK) 的空闲电平状态以及数据采样/切换的边沿。这两个参数通常组合为 4 种模式 (Mode 0 ~ Mode 3)。

SPI 模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据切换边沿
Mode 0 0 0 低电平 第一个跳变沿 (上升沿) 第二个跳变沿 (下降沿)
Mode 1 0 1 低电平 第二个跳变沿 (下降沿) 第一个跳变沿 (上升沿)
Mode 2 1 0 高电平 第一个跳变沿 (下降沿) 第二个跳变沿 (上升沿)
Mode 3 1 1 高电平 第二个跳变沿 (上升沿) 第一个跳变沿 (下降沿)
开发提示: 绝大多数 SPI 从设备默认使用 Mode 0 (CPOL=0, CPHA=0) 或 Mode 3 (CPOL=1, CPHA=1)。在配置前,务必查阅目标从设备的数据手册中的时序图,确认其要求的 SCK 空闲电平和采样边沿。

下图展示了 Mode 0 和 Mode 3 的典型时序差异,重点关注 SCK 空闲电平与数据采样点的位置。

SPI 时序:Mode 0 与 Mode 3 对比 Mode 0 (CPOL=0, CPHA=0) SCK ↑采样 ↑采样 ↑采样 Mode 3 (CPOL=1, CPHA=1) SCK ↑采样 ↑采样 ↑采样 关键区别:Mode 0 空闲为低,在第一个边沿 (上升沿) 采样;Mode 3 空闲为高,在第二个边沿 (上升沿) 采样。

4.2 数据帧格式:8 位与 16 位

SPI 外设支持可编程的数据帧长度,通常为 8 位 或 16 位。此设置决定了每次片选 (CS) 有效期间,通过 MOSI/MISO 线传输的数据位数。

  • 8 位数据帧 (DS=0): 最常用模式,兼容绝大多数 SPI 传感器、存储器 (如 Flash, EEPROM) 和 ADC 芯片。每次传输一个字节。
  • 16 位数据帧 (DS=1): 用于某些高速 DAC、音频编解码器或特定协议设备。一次传输两个字节,效率更高,但需确保从设备支持。
配置陷阱: 当主设备配置为 16 位帧格式,而从设备仅支持 8 位时,通信将完全错位。务必通过数据手册确认从设备的帧格式要求。对于支持 8 位/16 位混合通信的 MCU,通常需要软件干预来切换寄存器。

4.3 波特率设置

SPI 波特率决定了 SCK 时钟的频率,直接影响通信速度。波特率通常由 MCU 系统时钟 (PCLK) 经过分频得到。

计算公式:

SPI_波特率 = PCLK / 分频系数

常见的分频系数包括 2、4、8、16、32、64、128、256。例如,当 PCLK = 72 MHz 时:

分频系数 SPI 波特率 典型应用场景
2 36 MHz 高速 Flash、SRAM
4 18 MHz 高速 ADC、LCD 驱动
8 9 MHz 通用传感器、EEPROM
16 4.5 MHz 低速传感器、隔离通信
64 1.125 MHz 长线缆、抗干扰场景
波特率选择原则:
  1. 从设备上限: 波特率不得超过从设备数据手册标称的最大 SCK 频率。
  2. 信号完整性: 在 PCB 走线较长或环境干扰较大时,适当降低波特率以保证数据无误。
  3. DMA 传输考量: 在轮询模式下,波特率受 CPU 处理速度限制;若后续启用 DMA,可尝试使用更高分频系数以释放 CPU 负载。

4.4 配置流程与代码示例

以下代码展示了在 STM32 HAL 库中如何配置 SPI1 为 Mode 0、8 位数据帧、8 MHz 波特率 (假设 PCLK=72 MHz)。

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_8; // 72/8 = 9 MHz
    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();
    }
}

下图总结了 SPI 基础配置的完整决策流程,帮助开发者在初始化时快速定位参数。

SPI 基础配置决策流程 开始 SPI 配置 步骤1:查阅从设备数据手册 步骤2:确定 CPOL / CPHA 模式 步骤3:设置数据帧 (8位/16位) 步骤4:计算并设置波特率

4.5 常见配置错误与排查

  • 时钟模式不匹配: 主设备使用 Mode 0,从设备使用 Mode 3,导致数据采样点错误。排查时使用示波器测量 SCK 空闲电平。
  • 帧格式不一致: 主设备配置为 16 位,从设备仅支持 8 位,导致数据移位。检查数据手册中的帧格式说明。
  • 波特率过高: 从设备无法响应高速 SCK,导致数据读出为 0xFF 或随机值。尝试降低分频系数。
  • MSB/LSB 顺序错误: 部分设备要求 LSB 先行,若配置为 MSB 先行,数据会反向。确认 FirstBit 配置。