2. 硬件接口基础:SPI总线协议详解(四线制、时钟极性、相位、主从模式)

SPI(Serial Peripheral Interface,串行外设接口)是嵌入式系统中应用最广泛的同步串行通信协议之一,由摩托罗拉公司在20世纪80年代中期提出。在网关设备中,SPI常用于连接高速ADC/DAC、LCD控制器、RF模块、SD卡以及各类传感器。理解SPI的四线制结构、时钟极性与相位配置以及主从模式是驱动开发的基础。

2.1 SPI四线制信号定义

标准的SPI总线采用四线制连接,每条信号线都有明确的方向和功能。下表列出了四根信号线的名称与作用:

信号线 全称 方向(主设备视角) 功能描述
SCLK Serial Clock 输出 由主设备产生的同步时钟信号,决定数据传输速率
MOSI Master Out Slave In 输出 主设备发送数据到从设备的数据线
MISO Master In Slave Out 输入 从设备发送数据到主设备的数据线
SS Slave Select 输出 片选信号,低电平有效,用于选择与主设备通信的从设备
关键概念:SPI是全双工通信协议。在每一个时钟周期内,主设备通过MOSI发送一位数据,同时从设备通过MISO返回一位数据。这意味着SPI的收发操作是同步完成的,不存在单独的“发送”和“接收”阶段。

下图展示了SPI四线制总线中主设备与单个从设备的典型连接拓扑:

SPI四线制主从连接拓扑图 主设备 (Master) SCLK / MOSI / MISO / SS 从设备 (Slave) SCLK / MOSI / MISO / SS SCLK MOSI MISO SS (片选) SS线低电平有效:主设备将SS拉低时,从设备被选中并开始通信

2.2 时钟极性与时钟相位

SPI协议的核心灵活性体现在时钟极性(CPOL,Clock Polarity)和时钟相位(CPHA,Clock Phase)这两个配置参数上。它们共同决定了数据采样和切换的时序关系。

  • CPOL(时钟极性):定义SCLK在空闲状态(无数据传输时)的电平。
    • CPOL = 0:空闲时SCLK为低电平。
    • CPOL = 1:空闲时SCLK为高电平。
  • CPHA(时钟相位):定义数据采样发生在SCLK的哪个边沿。
    • CPHA = 0:在SCLK的第一个边沿(上升沿或下降沿,取决于CPOL)采样数据。
    • CPHA = 1:在SCLK的第二个边沿采样数据。

通过组合CPOL和CPHA,SPI支持四种工作模式,如下表所示:

模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据切换边沿
模式0 0 0 低电平 上升沿(第一个边沿) 下降沿
模式1 0 1 低电平 下降沿(第二个边沿) 上升沿
模式2 1 0 高电平 下降沿(第一个边沿) 上升沿
模式3 1 1 高电平 上升沿(第二个边沿) 下降沿
驱动开发常见错误:主设备和从设备的SPI模式必须完全一致。如果主设备配置为模式0(CPOL=0, CPHA=0),而从设备要求模式3(CPOL=1, CPHA=1),则通信将完全失败,数据采样会错位一个时钟周期。在Linux内核中,通过 spi_device->mode 字段设置模式,例如 SPI_MODE_0 到 SPI_MODE_3。

下图以模式0(CPOL=0, CPHA=0)为例,展示一个字节(0x53)的传输时序:

SPI模式0时序图(CPOL=0, CPHA=0) SPI模式0 时序示例(CPOL=0, CPHA=0) SCLK 1 2 3 4 5 6 7 8 MOSI 0 1 0 1 0 0 1 1 采样点 发送数据:0x53 = 二进制 0101 0011 模式0:空闲低电平,上升沿采样数据,下降沿切换数据

2.3 主从模式与多设备拓扑

SPI总线采用主从(Master-Slave)架构。主设备负责产生时钟信号并控制片选线,从设备被动响应。在网关硬件中,一个SPI主控制器通常需要挂载多个从设备。

多设备连接有两种常见拓扑:

  • 独立片选(Independent Slave Select):每个从设备使用独立的SS线,主设备通过拉低对应SS线来选择目标设备。这是最常用的方式,支持任意数量从设备(受限于主设备GPIO数量)。
  • 菊花链(Daisy Chain):所有从设备共享SS和SCLK,数据从主设备依次经过每个从设备再返回。这种方式节省引脚,但延迟较大,且要求从设备支持菊花链模式。

下图展示了网关中常见的独立片选多设备拓扑:

SPI多设备独立片选拓扑 SPI主控制器 (Master) SCLK / MOSI / MISO SS1 / SS2 / SS3 从设备1 RF模块 SS1 从设备2 ADC芯片 SS2 从设备3 LCD控制器 SS3 SS1 SS2 SS3 SCLK MOSI MISO

2.4 SPI传输流程与数据帧格式

一次完整的SPI数据传输遵循以下步骤:

  1. 片选激活:主设备将目标从设备的SS线从高电平拉低,通知从设备准备通信。
  2. 时钟启动:主设备开始产生SCLK时钟信号,频率由主设备的时钟分频器决定。
  3. 数据移位:在每个时钟周期内,主设备和从设备通过移位寄存器同步交换一位数据。MOSI线上的数据由主设备发出,MISO线上的数据由从设备发出。
  4. 帧结束:传输完指定字节数后,主设备停止SCLK,并将SS线拉高,释放从设备。
Linux内核中的SPI传输结构:在驱动开发中,SPI传输通过 struct spi_transfer 描述,支持散聚(scatter-gather)方式,即一次消息可以包含多个不连续的缓冲区。以下是一个典型的SPI写-读传输代码片段:
struct spi_transfer t[2] = {
    [0] = {
        .tx_buf = tx_buffer,   // 发送缓冲区
        .len    = 4,            // 发送4字节命令
    },
    [1] = {
        .rx_buf = rx_buffer,   // 接收缓冲区
        .len    = 16,          // 接收16字节数据
    },
};
struct spi_message msg;
spi_message_init(&msg);
spi_message_add_tail(&t[0], &msg);
spi_message_add_tail(&t[1], &msg);
spi_sync(spi_device, &msg);   // 同步执行传输

2.5 SPI与I2C的对比(网关选型参考)

在网关外设驱动开发中,SPI和I2C是最常用的两种总线。下表从驱动开发角度对比两者的关键差异:

对比维度 SPI I2C
信号线数量 4线(SCLK, MOSI, MISO, SS) 2线(SCL, SDA)
通信方式 全双工 半双工
最大速率 通常10-50 MHz,可达100 MHz+ 标准100 kHz,快速400 kHz,高速3.4 MHz
从设备选择 硬件片选(SS线) 软件寻址(7位或10位地址)
数据帧格式 无固定格式,主设备决定 固定格式:起始位 + 地址 + 读/写位 + 数据 + 应答位
多主设备支持 不支持(单主设备) 支持(多主设备仲裁)
Linux内核驱动接口 spi_sync() / spi_async() i2c_transfer() / i2c_smbus_*()
典型网关应用 高速ADC、RF模块、LCD、FPGA配置 传感器、RTC、EEPROM、温度监控
网关选型建议:当外设需要高速、连续、大数据量传输(如射频数据采集、LCD刷新)时,优先选择SPI。当外设对速率要求不高,但需要多设备共享总线且引脚受限时(如多个传感器),I2C更为合适。在网关主板上,两者通常共存,分别服务于不同速率等级的外设。

2.6 本章小结

SPI总线协议的核心要点可归纳为:

  • 四线制:SCLK、MOSI、MISO、SS,支持全双工同步通信。
  • 四种模式:由CPOL和CPHA组合决定,主从设备必须匹配。
  • 主从架构:主设备控制时钟和片选,从设备被动响应。
  • 多设备拓扑:独立片选是最常用方式,菊花链适用于特定场景。
  • 驱动开发要点:正确配置模式、速率和片选逻辑,使用 spi_transfer 和 spi_message 构建传输。