3. 片选信号(CS)核心作用:硬件连接、电平触发与多从机拓扑

片选信号(Chip Select,CS)是 SPI 总线中主设备与从设备建立通信的“握手信号”。在嵌入式 Linux 驱动开发中,CS 的硬件连接方式、电平触发逻辑以及多从机拓扑结构直接决定了驱动程序的时序控制策略和性能调优空间。本节从硬件原理出发,深入分析 CS 信号的核心作用。

3.1 CS 信号的硬件连接与电平触发方式

SPI 协议规定 CS 信号为低电平有效(Active Low)。当主设备需要与某个从设备通信时,将该从设备对应的 CS 引脚拉低,表示选中该设备;通信结束后,将 CS 拉高,释放总线。

信号状态 电平 含义
CS 拉低 0 V(低电平) 从设备被选中,开始接收/发送数据
CS 拉高 VCC(高电平) 从设备被释放,忽略总线上的时钟和数据
设计要点:低电平有效的好处在于,当主设备未初始化或复位时,CS 引脚默认处于高阻或高电平状态,从设备不会误触发。这是工业级通信可靠性的基本保障。

硬件连接上,主设备的 CS 引脚通常为 GPIO 或专用片选输出,直接连接到从设备的 CS 输入引脚。对于多从机系统,每个从设备需要独立的 CS 引脚。

典型连接示例(单从机):
主设备 (Master)         从设备 (Slave)
  SCK  ---------------->  SCK
  MOSI ---------------->  MOSI
  MISO <----------------  MISO
  CS   ---------------->  CS   (低电平有效)

3.2 多从机拓扑结构

SPI 总线支持多种多从机拓扑,最常见的两种是独立片选拓扑和菊花链拓扑。在嵌入式 Linux 驱动中,独立片选拓扑是主流选择。

3.2.1 独立片选拓扑(Parallel CS)

每个从设备拥有独立的 CS 引脚,主设备通过分别控制各 CS 引脚来选择通信对象。SCK、MOSI、MISO 信号线为所有从设备共享。

  • 优点:任意时刻只与一个从设备通信,无总线冲突;驱动实现简单,时序可控。
  • 缺点:占用主设备 GPIO 资源较多;从设备数量受限于主设备的 CS 引脚数。
  • 适用场景:大多数嵌入式系统,如传感器阵列、ADC/DAC 多通道采集。
驱动注意事项:在独立片选拓扑中,驱动必须确保在切换 CS 时,前一个从设备已完全释放总线(MISO 变为高阻),否则会造成数据冲突。通常需要在 CS 拉高后插入至少半个 SCK 周期的等待时间。

3.2.2 菊花链拓扑(Daisy-Chain)

所有从设备共享同一 CS 信号,数据通过从设备内部的移位寄存器依次传递。主设备的 MOSI 连接到第一个从设备的 DIN,第一个从设备的 DOUT 连接到第二个从设备的 DIN,以此类推。

  • 优点:仅需一个 CS 引脚,节省主设备资源。
  • 缺点:数据传输延迟随从设备数量线性增加;所有从设备必须支持菊花链模式;驱动需要计算总数据长度。
  • 适用场景:LED 驱动、移位寄存器扩展等对实时性要求不高的场合。

3.3 多从机拓扑结构对比

特性 独立片选拓扑 菊花链拓扑
CS 引脚数量 N(N 为从设备数) 1
数据传输延迟 低(直接通信) 高(逐级传递)
驱动复杂度 低 中高
从设备硬件要求 标准 SPI 接口 支持菊花链模式
典型应用 传感器、ADC、存储器 LED 驱动、移位寄存器

3.4 CS 信号时序与多从机拓扑 SVG 图

下图展示了独立片选拓扑下,主设备与两个从设备之间的 CS 信号连接关系以及数据流向。注意每个从设备拥有独立的 CS 线,而 SCK、MOSI、MISO 为共享总线。

SPI 独立片选多从机拓扑与 CS 信号连接 主设备 (Master) 从设备 1 (Slave 1) 从设备 2 (Slave 2) SCK (共享) MOSI (共享) MISO (共享) CS1 (独立) CS2 (独立) 说明: 主设备通过独立的 CS1 和 CS2 分别选中从设备 1 或从设备 2,SCK/MOSI/MISO 为共享总线。

3.5 CS 信号在驱动中的关键作用

在嵌入式 Linux SPI 驱动中,CS 信号的控制涉及以下三个关键层面:

  1. GPIO 控制:驱动通过 GPIO 子系统或 SPI 控制器硬件自动控制 CS 引脚的电平切换。
  2. 时序延迟:CS 拉低后到第一个 SCK 边沿之间的建立时间(CS Setup Time),以及最后一个 SCK 边沿后到 CS 拉高的保持时间(CS Hold Time),需要在设备树或驱动中配置。
  3. 多从机切换:驱动在切换 CS 时,必须确保前一次传输的 MISO 总线已释放,避免数据冲突。
设备树中 CS 时序配置示例(以 i.MX6ULL 为例):
&ecspi1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ecspi1>;
    cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>,   // CS0
               <&gpio4 27 GPIO_ACTIVE_LOW>;   // CS1
    fsl,spi-num-chipselects = <2>;
    status = "okay";

    spidev0: spi@0 {
        compatible = "spidev";
        reg = <0>;                 // 对应 CS0
        spi-max-frequency = <1000000>;
        spi-cs-setup-delay-ns = <100>;   // CS 建立时间
        spi-cs-hold-delay-ns = <100>;    // CS 保持时间
    };

    spidev1: spi@1 {
        compatible = "spidev";
        reg = <1>;                 // 对应 CS1
        spi-max-frequency = <2000000>;
    };
};

3.6 常见问题与避坑指南

问题现象 可能原因 解决方案
从设备无响应 CS 未正确拉低,或 GPIO 配置错误 检查设备树中 cs-gpios 的 GPIO 号与电气极性
数据错位 CS 建立时间不足,从设备未准备好 增加 spi-cs-setup-delay-ns 的值
多从机数据冲突 前一个从设备 MISO 未释放 在 CS 拉高后插入等待周期,或检查从设备三态输出特性
CS 毛刺导致误触发 GPIO 驱动能力不足或走线过长 增加上拉电阻,或使用 SPI 控制器的硬件 CS 功能
经验法则:在驱动调试阶段,优先使用逻辑分析仪抓取 CS 与 SCK 的时序关系,确认 CS 拉低到第一个 SCK 边沿的时间是否满足从设备数据手册的要求。通常建议 CS 建立时间不低于 50 ns。