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和采样点关系:
从这张图可以清楚看到:模式0和模式3的采样点都在上升沿,但空闲电平不同;模式1和模式2的采样点都在下降沿。DMA传输时,数据是连续流,采样点必须与从设备完全对齐。
1.4 DMA传输中的配置要点
在实际项目中,我总结了一套CPOL/CPHA配置检查清单:
- 确认从设备手册:先看从设备数据手册中SPI时序图,找到它要求的CPOL和CPHA。不要猜,不要假设。
- 配置主设备SPI寄存器:以STM32为例,在SPI_CR1寄存器中设置CPOL和CPHA位。注意:必须在SPI使能之前配置,否则行为未定义。
- 验证空闲电平:用示波器测量SCK空闲时的电平,确认与CPOL配置一致。低电平对应CPOL=0,高电平对应CPOL=1。
- 验证采样边沿:发送一个已知数据(如0x55),观察MOSI数据变化点与SCK边沿的关系,确认采样边沿正确。
- 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使能前完成
- 用示波器或逻辑分析仪验证时序