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 线:
硬件连接要点:
- 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 的时序关系:
1.3 数据传输流程
一次完整的 SPI 数据传输遵循以下步骤:
- 片选使能:主设备将目标从设备的 CS 引脚从高电平拉低,选中该从设备。
- 时钟启动:主设备根据配置的模式(CPOL/CPHA)开始产生 SCLK 时钟信号。
- 数据移位:在每个时钟边沿,主设备通过 MOSI 移出一位数据,同时从设备通过 MISO 移入一位数据。SPI 通常采用 MSB-first(高位先行)传输顺序。
- 数据完成:传输完指定字节数(通常为 8 位或 16 位)后,主设备停止 SCLK。
- 片选释放:主设备将 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 协议本身不提供数据校验或应答机制,可靠性依赖上层协议。