1. SPI 总线协议基础

SPI(Serial Peripheral Interface,串行外设接口)是由 Motorola 公司推出的一种高速、全双工、同步的串行通信总线。它被广泛用于连接微控制器与传感器、ADC/DAC、存储器、显示驱动等外设。本章从物理层、信号定义、时序模型和模式配置四个维度,系统梳理 SPI 协议的核心基础。

1.1 物理层与四线制信号

SPI 总线采用主从(Master-Slave)架构,通常由 4 根信号线组成,实现全双工同步通信。下表列出四线制的名称、方向和功能:

信号线 全称 方向(主设备视角) 功能描述
SCLK Serial Clock 输出 由主设备产生,同步数据传输的时钟信号
MOSI Master Out Slave In 输出 主设备发送数据至从设备
MISO Master In Slave Out 输入 从设备发送数据至主设备
CS Chip Select 输出 片选信号,低电平有效,选中特定从设备
关键概念:SPI 是全双工协议——在每个时钟周期内,主设备通过 MOSI 发送一位数据,同时从设备通过 MISO 返回一位数据。因此,一次传输总是同时完成发送和接收。

下图展示了一个典型 SPI 主-从连接的系统结构,包含一个主设备和三个从设备,每个从设备拥有独立的 CS 线:

SPI 主-从连接结构图 SPI 主设备 (Master) 从设备 1 (Slave) 从设备 2 (Slave) 从设备 3 (Slave) SCLK MOSI MISO CS (独立片选) 总线拓扑 SCLK/MOSI/MISO 共享,CS 独立
硬件连接要点:
  • SCLK、MOSI、MISO 为共享总线,所有从设备并联在这三根线上。
  • 每个从设备独占一根 CS 线,主设备通过拉低对应 CS 来选择通信目标。
  • 未选中的从设备必须将 MISO 引脚置为高阻态,避免总线冲突。
  • SPI 没有内置应答机制,主设备需通过协议层确认从设备是否正常响应。

1.2 SPI 时序与数据采样

SPI 的时序由时钟极性(CPOL)和时钟相位(CPHA)两个参数共同决定。CPOL 定义时钟空闲时的电平,CPHA 定义数据在时钟的哪个边沿被采样。两者组合形成 4 种工作模式。

模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据输出边沿
模式 0 0 0 低电平 上升沿 下降沿
模式 1 0 1 低电平 下降沿 上升沿
模式 2 1 0 高电平 下降沿 上升沿
模式 3 1 1 高电平 上升沿 下降沿
常见误区:许多初学者认为 CPOL=0 表示时钟上升沿有效,CPOL=1 表示下降沿有效。实际上 CPOL 只决定空闲电平,采样边沿由 CPHA 决定。模式 0(CPOL=0, CPHA=0)是最常用的模式,大多数 SPI 外设默认支持此模式。

下图以模式 0 和模式 3 为例,展示 SCLK、MOSI、MISO 和 CS 的时序关系:

SPI 模式 0 与模式 3 时序对比图 模式 0 (CPOL=0, CPHA=0) CS SCLK ▲ 采样 (上升沿) MOSI bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 模式 3 (CPOL=1, CPHA=1) CS SCLK ▲ 采样 (上升沿) MOSI bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 模式 0 和模式 3 都在时钟上升沿采样数据,区别仅在于空闲时钟电平(低 vs 高)

1.3 数据传输流程

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

  1. 片选使能:主设备将目标从设备的 CS 引脚从高电平拉低,选中该从设备。
  2. 时钟启动:主设备根据配置的模式(CPOL/CPHA)开始产生 SCLK 时钟信号。
  3. 数据移位:在每个时钟边沿,主设备通过 MOSI 移出一位数据,同时从设备通过 MISO 移入一位数据。SPI 通常采用 MSB-first(高位先行)传输顺序。
  4. 数据完成:传输完指定字节数(通常为 8 位或 16 位)后,主设备停止 SCLK。
  5. 片选释放:主设备将 CS 拉高,结束本次通信。
数据传输特点:
  • SPI 没有帧起始或停止位,CS 的下降沿和上升沿分别标志传输开始和结束。
  • 全双工特性意味着主设备在发送数据的同时,也在接收从设备返回的数据。如果只需要发送,主设备可以忽略 MISO 上的数据;如果只需要接收,主设备必须发送虚拟字节(通常为 0x00 或 0xFF)来产生时钟。
  • SPI 的传输速率理论上仅受限于 GPIO 或 SPI 控制器的最大时钟频率,典型范围从几百 kHz 到几十 MHz。

1.4 SPI 模式配置示例

在 Linux 内核中,SPI 设备的模式通过 spi_device 结构体的 mode 字段配置。以下代码片段展示如何在设备树或板级代码中设置 SPI 模式:

/* Linux SPI 设备模式配置示例 */
struct spi_device *spi;
u8 mode;

/* 设置为模式 0:CPOL=0, CPHA=0 */
mode = SPI_MODE_0;
spi->mode = mode;

/* 设置为模式 3:CPOL=1, CPHA=1 */
mode = SPI_MODE_3;
spi->mode = mode;

/* 常用宏定义(来自 linux/spi/spi.h):
 * #define SPI_MODE_0  (0|0)
 * #define SPI_MODE_1  (0|SPI_CPHA)
 * #define SPI_MODE_2  (SPI_CPOL|0)
 * #define SPI_MODE_3  (SPI_CPOL|SPI_CPHA)
 */
实践建议:在开发 SPI 设备驱动时,首先查阅从设备数据手册确认其支持的 SPI 模式。如果从设备支持多种模式,优先选择模式 0 或模式 3,因为这两种模式都在时钟上升沿采样,硬件实现更简单,兼容性更好。

1.5 本章小结

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

  • 四线制:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。
  • 主从架构:一个主设备可连接多个从设备,通过独立 CS 线进行选择。
  • 全双工同步:每个时钟周期同时完成一位数据的发送和接收。
  • 四种模式:由 CPOL(时钟极性)和 CPHA(时钟相位)组合决定,模式 0 最常用。
  • 无内置应答:SPI 协议本身不提供数据校验或应答机制,可靠性依赖上层协议。