2. SPI数据帧格式:8位/16位数据帧、MSB/LSB先行、时钟极性与相位对数据采样的影响

好,咱们接着聊SPI。上一章我们把SPI的四根线讲清楚了,这一章我重点说说数据到底怎么在线上跑。说白了,就是数据帧的格式问题。很多新手调SPI,调不通的原因往往不是硬件接错了,而是主从设备的帧格式没对上。我当年刚入行时就吃过这个亏,折腾了一整天,最后发现是MSB/LSB顺序搞反了。

2.1 数据帧长度:8位还是16位?

SPI协议本身没有规定一次必须传多少位。最常见的当然是8位,也就是一个字节。但很多MCU的SPI外设也支持16位帧格式。你想想看,如果你的传感器输出的是12位或16位数据,用8位帧就得传两次,还得拼数据,多麻烦。

核心要点:8位帧兼容性最好,16位帧效率更高。选择取决于外设的数据宽度。

我个人习惯是:如果从设备的数据寄存器是16位的,我优先用16位帧。比如一些高精度ADC、DAC、陀螺仪,它们的数据手册里明确写了“16-bit data word”,那就别硬拆成两个8位去传。

帧格式 典型应用场景 优点 缺点
8位 Flash存储器、温度传感器、通用外设 兼容性极广,几乎所有SPI设备都支持 传16位数据需两次传输,软件拼接麻烦
16位 音频Codec、高精度ADC/DAC、陀螺仪 一次传输完成16位数据,效率高 部分低端MCU不支持,或需特殊配置

小技巧:配置寄存器时,注意看SPI_CR1或SPI_CR2里的DFF位(Data Frame Format)。置1选16位,清0选8位。切换帧格式时,最好先把SPI外设禁能,改完再使能,否则容易出乱子。

2.2 位序:MSB先行还是LSB先行?

这个问题看似简单,但坑不少。SPI默认是MSB先行,也就是最高位先传。大多数设备都遵循这个约定。但有些奇葩外设,比如某些LED驱动芯片、LCD控制器,偏偏要用LSB先行。

为什么会这样?有些芯片内部的数据移位寄存器是从低位开始处理的,所以它们希望LSB先到。嗯,这里要注意:如果你主设备用MSB,从设备用LSB,那收到的数据就是反的。比如你想发0x80(二进制1000 0000),结果从设备收到的是0x01(0000 0001)。

避坑指南:我曾经在一个项目里,用STM32的SPI驱动一个LED点阵屏。屏幕怎么点都不亮,逻辑分析仪抓波形发现数据完全反了。查了三天手册,才发现那个LED驱动芯片要求LSB先行。把SPI的LSBFIRST位置1,问题立刻解决。

配置位序的寄存器位通常叫LSBFIRST或类似的名称。置1表示LSB先行,清0表示MSB先行。我建议你养成一个习惯:拿到一个新外设,第一件事就是看数据手册里关于数据格式的章节,确认位序。

2.3 时钟极性与相位:数据采样的关键

这部分是SPI协议里最容易让人晕的地方。时钟极性(CPOL)和时钟相位(CPHA)组合出四种模式。很多工程师把这四种模式背得滚瓜烂熟,但一到实际调试还是抓瞎。我换个角度给你讲,保证你听完就懂。

2.3.1 时钟极性(CPOL)

CPOL决定的是时钟空闲时的电平。说白了就是:没有数据传输时,SCK线是高电平还是低电平?

  • CPOL = 0:空闲时SCK为低电平。时钟脉冲是一个从低到高再回低的波形。
  • CPOL = 1:空闲时SCK为高电平。时钟脉冲是一个从高到低再回高的波形。

这个很好理解,对吧?

2.3.2 时钟相位(CPHA)

CPHA才是真正的难点。它决定的是数据在时钟的哪个边沿被采样。注意,是采样,不是输出。

  • CPHA = 0:数据在时钟的第一个边沿被采样。第一个边沿可能是上升沿(CPOL=0时),也可能是下降沿(CPOL=1时)。
  • CPHA = 1:数据在时钟的第二个边沿被采样。

你想想看,第一个边沿和第二个边沿,差了一个时钟周期。如果主从设备的CPHA没对上,数据就会错位一个时钟周期,结果就是全乱套。

记住这个口诀:CPHA=0,第一个边沿采样;CPHA=1,第二个边沿采样。采样边沿和CPOL无关,只和CPHA有关。

2.3.3 四种模式组合

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

最常用的模式是模式0和模式3。很多Flash芯片、SD卡都默认用模式0。但别想当然,一定要看数据手册。

SPI四种时钟模式波形对比 模式0 (CPOL=0, CPHA=0) SCK MOSI D7 D6 D5 D4 D3 D2 ↑采样 ↑采样 ↑采样 ↑采样 模式1 (CPOL=0, CPHA=1) SCK MOSI D7 D6 D5 D4 D3 D2 ↓采样 ↓采样 ↓采样 ↓采样 模式2 (CPOL=1, CPHA=0) SCK MOSI D7 D6 D5 D4 D3 D2 ↓采样 ↓采样 ↓采样 ↓采样 模式3 (CPOL=1, CPHA=1) SCK MOSI D7 D6 D5 D4 D3 D2 ↑采样 ↑采样 ↑采样 ↑采样 如何快速确定模式? 1. 看数据手册中时序图 2. 找SCK空闲电平(CPOL) 3. 找数据在哪个边沿采样(CPHA) 4. 用逻辑分析仪抓波形验证 常见设备默认模式 • 大多数Flash/SD卡:模式0 • 部分传感器:模式3 • 少数设备支持多种模式

2.4 实际配置中的注意事项

配置SPI数据帧格式时,我建议你按这个顺序来检查:

  1. 先看从设备数据手册,找到SPI时序图。图上会明确标出CPOL和CPHA的值。
  2. 确认数据帧长度,是8位还是16位。
  3. 确认位序,MSB还是LSB先行。
  4. 配置MCU的SPI寄存器,让主从设备完全一致。
  5. 用逻辑分析仪抓波形验证,别光靠眼睛看代码。

重要提醒:有些MCU的SPI外设,在改变CPOL或CPHA后,必须重新初始化才能生效。我遇到过的情况是:改了寄存器但没重新使能SPI,结果波形还是老样子。调试了半天才发现是这个问题。