一句话: CPOL 管空闲时时钟线是高还是低,CPHA 管第几个边沿锁数据。Mode 0=上升沿锁(CPHA=0),Mode 1=下降沿锁(CPHA=1)。设反了每个 bit 都在错误时刻采样——SPI 通信正常但数据全错。
适合谁读:SPI 能发能收但数据总是不对的嵌入式开发者。
四个模式一表搞定
SPI 有四种模式,由 CPOL 和 CPHA 两个位组合决定:
| Mode | CPOL | CPHA | 空闲时钟 | 锁存边沿 |
|---|---|---|---|---|
| 0 | 0 | 0 | 低电平 | 上升沿(第一个边沿) |
| 1 | 0 | 1 | 低电平 | 下降沿(第二个边沿) |
| 2 | 1 | 0 | 高电平 | 下降沿(第一个边沿) |
| 3 | 1 | 1 | 高电平 | 上升沿(第二个边沿) |
CPOL 是 Clock Polarity——时钟极性。管的是"不传数据时时钟线什么状态"。0=低,1=高。
CPHA 是 Clock Phase——时钟相位。管的是"第几个边沿锁数据"。0=第一个边沿锁,1=第二个边沿锁。
大多数器件用的是 Mode 0 或 Mode 3。具体哪个要看手册的时序图。
设反了是什么现象
代码把 CPHA 设成了 1(Mode 1,下降沿锁存),但芯片手册要求 CPHA=0(Mode 0,上升沿锁存)。
结果:SPI 波形在示波器上看一切正常——SCK 在跳、MOSI 在发、CS 在拉低——但芯片就是不工作。因为芯片在每个 SCK 的下降沿尝试锁数据,而主机的数据在上升沿就变了。芯片锁到的永远是错误时刻的数据。
就像两个人击掌——你觉得在数"一"的时候合掌,对方觉得在数"二"的时候合掌。你们都在拍手,但永远拍不到一起。不疼,但不对。
怎么查
接示波器看 SCK 和 MOSI 的相位关系。在 Mode 0 下:SCK 上跳时 MOSI 数据已稳定,芯片在这个边沿采样。在 Mode 1 下:SCK 下跳时采样,但此时 MOSI 可能正在切换。
数据手册的时序图里会画一条竖虚线标注"数据锁存时刻"。找到那条虚线对应的边沿,就知道 CPOL 和 CPHA 该设什么。
代码改法
// 改前:Mode 1 (CPHA=1, 下降沿锁) SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; // 改后:Mode 0 (CPHA=0, 上升沿锁) SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;改一个枚举值,所有调不通的器件全活了。
有用的话点个收藏,下次调试直接用。有问题欢迎评论区交流,看到了都会回。