3. 多设备级联拓扑:独立片选与菊花链

SPI 总线上挂多个设备,这事我做过不少。但很多新手一上来就问:「能不能把所有设备的 CS 都接在一起?」嗯,理论上可以,但实际坑很多。今天咱们就把两种主流拓扑——独立片选(Parallel)和菊花链(Daisy-Chain)——彻底讲透。

3.1 独立片选(Parallel)模式

这是最常用的方式。每个设备有自己的片选线,主机通过拉低对应 CS 来选择通信对象。说白了,就是「点对点」的扩展。

典型连接方式:
MOSI → 所有设备的 MOSI
MISO → 所有设备的 MISO
SCLK → 所有设备的 SCLK
CS0 → 设备0
CS1 → 设备1
CS2 → 设备2

我刚开始做多设备系统时,用的就是这种方案。为什么?因为逻辑简单,调试方便。每个设备独立操作,互不干扰。

优点

  • 时序独立:每个设备可以有不同的时钟极性和相位(CPOL/CPHA)
  • 速度不受限:每个设备都能跑满自己的最高速率
  • 调试友好:用逻辑分析仪抓一根 CS 线就能定位问题
  • 故障隔离:一个设备挂了,不影响其他设备通信

缺点

  • 占用 IO 多:N 个设备需要 N 根 CS 线
  • PCB 布线复杂:尤其是高速信号,多根 CS 线容易串扰
  • 主机资源受限:MCU 的 GPIO 数量有限,挂太多设备不现实

3.2 菊花链(Daisy-Chain)模式

菊花链就有点意思了。所有设备共用一根 CS 线,数据像「接力棒」一样从一个设备传到下一个。MOSI 连第一个设备的输入,第一个设备的输出连第二个设备的输入,以此类推。

关键点:菊花链要求设备必须支持「数据转发」功能。不是所有 SPI 设备都支持,买芯片前一定要看 datasheet 里的 Daisy-Chain 支持标志。

我记得有一次项目,FPGA 需要同时配置 8 个 ADC。如果用独立片选,FPGA 的 IO 根本不够。后来改用菊花链,一根 CS 搞定。但调试过程……嗯,一言难尽。

优点

  • 节省 IO:无论多少设备,只需要 1 根 CS
  • 布线简单:信号线少,PCB 布局压力小
  • 扩展性强:理论上可以无限级联(受限于时序和驱动能力)

缺点

  • 速度受限:数据要经过每个设备转发,延迟累积
  • 时序要求严格:所有设备必须使用相同的 CPOL/CPHA
  • 调试困难:一个设备出问题,整条链都废了
  • 故障难定位:数据传错了,你不知道是哪个设备搞的鬼

3.3 两种模式对比

对比项 独立片选(Parallel) 菊花链(Daisy-Chain)
CS 线数量 N 根 1 根
最大速率 每个设备独立最高速 受限于最慢设备 + 转发延迟
时钟极性 可独立配置 必须统一
调试难度 低 高
故障影响 单设备故障 整链瘫痪
PCB 复杂度 高 低
典型应用 传感器阵列、多协议设备 ADC/DAC 级联、LED 驱动

3.4 实际场景选择

你可能会问:「那我到底该用哪种?」我的建议是——看场景。

选独立片选的情况:
  • 设备类型不同(比如一个 ADC + 一个 DAC + 一个传感器)
  • 对速率要求高
  • 调试阶段,需要快速定位问题
  • 主机 IO 资源充足
选菊花链的情况:
  • 设备类型相同(比如 8 个相同的 ADC)
  • 主机 IO 紧张
  • PCB 空间有限,布线困难
  • 对成本敏感(减少 IO 意味着可以用更便宜的 MCU)

我曾经在一个项目中,为了省 IO 选了菊花链。结果调试时发现第三个设备的数据总是错位。查了三天,最后发现是第二个设备的 MISO 输出驱动能力不够,导致信号畸变。从那以后,我养成了一个习惯:能用独立片选就别用菊花链,除非你做好了调试地狱的心理准备。

3.5 拓扑结构图

下面这张图把两种拓扑画清楚了。左边是独立片选,右边是菊花链。注意看 CS 线的连接方式差异。

SPI 多设备拓扑对比 独立片选(Parallel) 主机 设备0 设备1 设备2 CS0 CS1 CS2 菊花链(Daisy-Chain) 主机 设备0 设备1 设备2 公共 CS 关键差异 独立片选:每设备独立 CS,可单独配置时钟,调试方便 菊花链:共用 CS,数据逐级转发,节省 IO 但调试困难

3.6 避坑指南

我曾经踩过的坑:
  1. 菊花链的时序余量:每个设备转发数据会引入 1-2 个时钟周期的延迟。级联 8 个设备,延迟可能超过 16 个时钟周期。如果你的数据帧很短,可能还没传到最后一个设备,CS 就拉高了。
  2. 独立片选的信号质量:多根 CS 线并行布线,容易产生串扰。我遇到过 CS 线之间的耦合导致误触发。解决办法是加地线隔离,或者拉大间距。
  3. 设备不支持菊花链:有些芯片 datasheet 里没写 Daisy-Chain,但实际可以「硬接」。不过我不建议这么干——出了问题你都不知道找谁。
我的调试习惯:
如果是新板子,我会先用独立片选模式验证每个设备单独通信正常。确认无误后,再切换到菊花链模式。这样出了问题,至少能排除设备本身的问题。

好了,两种拓扑的对比就到这里。你想想看,你的项目里 IO 够不够?设备类型是否统一?调试时间是否充裕?想清楚这三个问题,选哪种方案自然就明白了。