1. SPI协议基础回顾:时钟极性(CPOL)与相位(CPHA)配置对DMA传输的影响

SPI通信,说白了就是主从设备之间通过四根线(SCK、MOSI、MISO、CS)进行同步数据交换。很多初学者觉得SPI简单,不就是配置几个寄存器吗?但真到了DMA传输场景下,CPOL和CPHA配错了,数据就全乱了。我最早踩这个坑是在一个高速数据采集项目上,主频跑到了36MHz,波形抓出来全是错位的,查了整整两天才发现是时钟相位差了一个边沿。

1.1 时钟极性(CPOL)与相位(CPHA)的本质

先看SPI的四种模式。CPOL决定时钟空闲电平,CPHA决定数据采样时刻。这两个位组合起来,就形成了四种工作模式:

模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据变化边沿
模式0 0 0 低电平 上升沿 下降沿
模式1 0 1 低电平 下降沿 上升沿
模式2 1 0 高电平 下降沿 上升沿
模式3 1 1 高电平 上升沿 下降沿

这里有个关键点:采样边沿和变化边沿是互补的。数据在变化边沿准备好,在采样边沿被读取。如果主从设备的采样/变化边沿对不上,数据就会错位一个时钟周期。

核心原则:主设备和从设备的SPI模式必须完全一致。CPOL和CPHA任何一个不匹配,通信就会失败。

1.2 CPOL/CPHA对DMA传输的直接影响

为什么DMA传输下CPOL/CPHA配置更敏感?我总结了两点:

  • 时序窗口变窄:DMA传输通常跑在较高时钟频率下(几十MHz),时钟周期只有几十纳秒。CPOL/CPHA决定了数据采样点相对于时钟边沿的位置,如果配置不当,建立时间和保持时间很容易被违反。
  • 连续传输无停顿:DMA模式下,数据是连续流式传输的,不像CPU轮询那样每字节之间有间隔。连续传输意味着没有"喘息"机会,时钟边沿必须精确对齐。

举个例子。我曾经调试一个STM32H7与FPGA的SPI DMA通信,FPGA要求模式2(CPOL=1, CPHA=0),但我习惯性配成了模式0。结果DMA传输的前几个字节是对的,后面全乱了。为什么?因为模式0下数据在下降沿变化、上升沿采样,而FPGA期望的是下降沿采样。前几个字节因为CS拉低后的初始状态恰好对齐,但连续传输后相位差累积,数据就错位了。

避坑指南:我曾经在切换SPI从设备时忘记重新配置CPOL/CPHA,导致DMA传输的数据全部偏移了一个位。后来我养成了一个习惯:每次初始化SPI外设时,都显式地重新配置CPOL和CPHA,绝不依赖默认值或上次配置。

1.3 四种模式下的DMA传输时序对比

为了更直观地理解,我画了一张时序对比图。这张图展示了在相同数据(0x55)下,四种模式的SCK、MOSI和采样点关系:

SPI四种模式DMA传输时序对比 SPI四种模式DMA传输时序对比(数据0x55) 模式0 (CPOL=0, CPHA=0) SCK MOSI 0 1 0 1 0 1 0 1 模式1 (CPOL=0, CPHA=1) SCK 模式2 (CPOL=1, CPHA=0) SCK 模式3 (CPOL=1, CPHA=1) SCK SCK时钟 采样点 ● MOSI数据 注意:模式0和模式3采样点在上升沿,模式1和模式2在下降沿

从这张图可以清楚看到:模式0和模式3的采样点都在上升沿,但空闲电平不同;模式1和模式2的采样点都在下降沿。DMA传输时,数据是连续流,采样点必须与从设备完全对齐。

1.4 DMA传输中的配置要点

在实际项目中,我总结了一套CPOL/CPHA配置检查清单:

  1. 确认从设备手册:先看从设备数据手册中SPI时序图,找到它要求的CPOL和CPHA。不要猜,不要假设。
  2. 配置主设备SPI寄存器:以STM32为例,在SPI_CR1寄存器中设置CPOL和CPHA位。注意:必须在SPI使能之前配置,否则行为未定义。
  3. 验证空闲电平:用示波器测量SCK空闲时的电平,确认与CPOL配置一致。低电平对应CPOL=0,高电平对应CPOL=1。
  4. 验证采样边沿:发送一个已知数据(如0x55),观察MOSI数据变化点与SCK边沿的关系,确认采样边沿正确。
  5. DMA配置一致性:确保DMA传输的数据宽度(8位/16位/32位)与SPI数据帧格式一致。不一致时,即使CPOL/CPHA正确,数据也会错位。

个人经验:我习惯在SPI初始化代码中加一段自检逻辑:发送一个固定字节(如0xAA),然后读取回环数据(如果硬件支持)。如果回读数据与发送数据一致,说明CPOL/CPHA配置正确。这个方法帮我快速定位过好几次配置错误。

1.5 常见问题与调试方法

DMA传输中CPOL/CPHA配置错误的表现通常有几种:

现象 可能原因 排查方法
第一个字节正确,后续全错 CPHA配置错误,导致采样点偏移 用示波器对比SCK和MOSI边沿关系
所有数据都错位1位 CPOL配置错误,空闲电平不匹配 测量SCK空闲电平,与CPOL对比
数据时对时错 时钟频率过高,建立时间不足 降低SPI时钟频率测试
DMA传输完成但数据全为0 CPOL/CPHA导致从设备未正确识别CS 检查CS时序与SPI模式的配合

调试时我建议先用低速模式(1MHz以下)验证CPOL/CPHA配置,确认无误后再提升到目标频率。高速下时序问题更难排查,低速能帮你把配置问题先排除掉。

重要提醒:有些MCU的SPI外设在DMA模式下,CPOL/CPHA的配置会影响DMA请求的触发时机。比如,某些芯片在CPHA=0时,DMA请求在第一个时钟边沿触发;CPHA=1时,在第二个时钟边沿触发。这个细节在数据手册里往往藏在角落,但踩到就是大坑。

1.6 本章小结

CPOL和CPHA看似简单,但在DMA传输场景下,配置错误会导致数据完全错乱。核心就三点:

  • 主从设备的SPI模式必须一致
  • 配置必须在SPI使能前完成
  • 用示波器或逻辑分析仪验证时序