3. SPI通信协议详解

SPI,全称是Serial Peripheral Interface,串行外设接口。在BMS系统里,它是我最常用的片间通信方式之一。为什么?因为简单、快、而且硬件开销小。你想想看,一个隔离SPI,只需要四根线穿过隔离屏障,就能把ADC、数字隔离器、甚至MCU之间的数据跑起来。

但简单归简单,坑也不少。我刚开始做BMS隔离设计时,就因为在SPI模式上栽过跟头——板子调了两天,波形怎么看都对,数据就是乱码。后来发现,主从设备的CPOL和CPHA没对上。嗯,这种经历一次就记住了。

3.1 SPI四线制:SCK、MOSI、MISO、CS

标准的SPI接口有四根信号线。咱们一个一个说清楚。

信号 全称 方向(主→从) 作用
SCK Serial Clock 主→从 时钟信号,由主机产生
MOSI Master Out Slave In 主→从 主机发送数据给从机
MISO Master In Slave Out 从→主 从机发送数据给主机
CS Chip Select 主→从 片选信号,低电平有效

这里有个细节我提醒你注意:CS信号在隔离设计中往往被忽略。很多工程师只隔离SCK、MOSI、MISO三根线,觉得CS是控制信号,不传数据,随便拉一下就行。我在一个12串BMS项目里就这么干过,结果从机在CS切换时产生了毛刺,导致数据错位。后来老老实实把CS也一起隔离了,问题才解决。

注意:在BMS隔离SPI设计中,CS信号必须与SCK、MOSI、MISO一起通过隔离器件。不要为了省一路隔离通道而把CS直连,否则可能引入共模噪声或电平不匹配问题。

3.2 SPI模式:CPOL与CPHA

SPI有四种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)组合决定。说白了,就是决定时钟在什么状态下是空闲,以及数据在时钟的哪个边沿采样。

  • CPOL:时钟极性。CPOL=0时,空闲状态SCK为低电平;CPOL=1时,空闲状态SCK为高电平。
  • CPHA:时钟相位。CPHA=0时,数据在第一个边沿采样;CPHA=1时,数据在第二个边沿采样。

四种模式如下表:

模式 CPOL CPHA 采样边沿 空闲时钟电平
模式0 0 0 上升沿 低
模式1 0 1 下降沿 低
模式2 1 0 下降沿 高
模式3 1 1 上升沿 高
我的习惯:在BMS项目中,我通常默认使用SPI模式0(CPOL=0,CPHA=0)。因为大多数ADC和数字隔离器都支持模式0,兼容性最好。但如果你用的从机芯片手册里写了别的模式,一定要改过来。我曾经因为没看手册,默认用模式0去驱动一个只支持模式3的隔离ADC,结果读回来的电压值全是乱的。

3.3 SPI速率与距离限制

SPI能跑多快?理论上,板内通信可以到几十MHz甚至上百MHz。但在BMS系统里,情况不一样。

我列几个实际工程中的典型数据:

  • 板内SPI(同一PCB):10MHz ~ 50MHz,距离<10cm。没问题。
  • 板间SPI(通过排线或FPC):1MHz ~ 10MHz,距离10cm~30cm。需要加终端匹配。
  • 隔离SPI(通过数字隔离器):1MHz ~ 20MHz,取决于隔离器延迟。我常用的ISO7241,典型延迟50ns,算下来最高能跑10MHz左右。
  • 长距离SPI(>1米):不建议。超过1米,信号完整性急剧下降,除非你用差分SPI或RS-422转接。
关键结论:在BMS隔离通信中,SPI速率通常被限制在1MHz~10MHz之间。瓶颈不在SPI协议本身,而在隔离器件的传播延迟和PCB走线的寄生参数。

为什么会这样?你想想看,隔离器内部是通过光耦或电容耦合传输信号的,每经过一次隔离,信号就有几十纳秒的延迟。如果时钟频率太高,数据还没传过去,下一个时钟边沿就来了——数据就乱了。

我记得有一次,客户要求把SPI速率从5MHz提到20MHz,我换了更快的隔离器(ISO7741,延迟15ns),结果还是不行。后来发现是PCB走线太长,信号反射严重。最后把走线缩短、加了串联电阻,才稳定在12MHz。嗯,速率和距离,永远是SPI设计里的一对矛盾。

3.4 SPI菊花链拓扑

标准SPI是一主多从,每个从机一根独立的CS线。但如果你有8个、16个从机呢?MCU的GPIO不够用怎么办?这时候菊花链(Daisy Chain)就派上用场了。

菊花链的原理很简单:所有从机的SCK和CS共用,MOSI连到第一个从机的输入,第一个从机的MISO连到第二个从机的MOSI输入……以此类推,最后一个从机的MISO连回主机的MISO。

数据像流水线一样,在每个时钟周期从上一个从机传到下一个从机。

SPI菊花链拓扑结构 主机 MCU 从机 1 从机 2 从机 3 从机 4 从机 5 从机 6 SCK(共用时钟) CS(共用片选) MOSI MISO MISO 回主机 数据流向:主机 → 从机1 → 从机2 → 从机3 → 从机4 → 从机5 → 从机6 → 主机

菊花链的好处很明显:节省GPIO。不管挂多少个从机,主机只需要3根线(SCK、MOSI、MISO)加一根CS。但代价是什么?

  • 延迟累加:每个从机都会引入几个时钟周期的延迟。链越长,延迟越大。
  • 数据吞吐量下降:要读取最后一个从机的数据,必须先让数据穿过前面所有从机。
  • 故障扩散:中间任何一个从机出问题,整条链都断了。
我的建议:在BMS中,菊花链适合从机数量不多(≤8个)、且对实时性要求不高的场景。比如用菊花链读取多个温度传感器的数据,每个传感器每秒更新一次,完全够用。但如果要同时采集多路电压和电流,我建议还是用独立CS或者改用CAN总线。