1. SPI 总线概述

1.1 SPI 协议简介

SPI(Serial Peripheral Interface,串行外设接口) 是由 Motorola 公司推出的一种高速、全双工、同步的串行通信总线。它广泛应用于嵌入式系统中连接微控制器与各种外设,如传感器、ADC/DAC、LCD 显示屏、SD 卡、Flash 存储器等。

SPI 总线的主要特点包括:

  • 主从架构:通信由主设备(Master)发起并控制时钟,从设备(Slave)响应。
  • 全双工通信:数据发送和接收可同时进行,互不干扰。
  • 同步传输:由主设备提供的串行时钟(SCLK)同步数据位流。
  • 高速率:典型时钟频率可达数十 MHz,远高于 I²C 总线。
  • 无应答机制:相比 I²C,SPI 没有内置的应答信号,协议开销更低。
提示: SPI 总线没有像 I²C 那样的设备地址寻址机制,而是通过独立的片选信号(CS)来选择从设备。这意味着每增加一个从设备,主设备就需要多占用一个 GPIO 引脚作为片选。

1.2 四线制工作原理

标准 SPI 总线使用四根信号线进行通信,下表总结了每根信号线的名称与功能:

信号线 全称 方向(主→从) 功能描述
SCLK Serial Clock 主 → 从 由主设备产生的串行时钟信号,同步数据传输的每一位。
MOSI Master Out Slave In 主 → 从 主设备输出数据,从设备接收数据。
MISO Master In Slave Out 从 → 主 从设备输出数据,主设备接收数据。
CS Chip Select 主 → 从 片选信号,低电平有效,用于选中特定的从设备。

四线制的工作流程如下:

  1. 片选阶段:主设备将目标从设备的 CS 引脚拉低,激活该从设备。
  2. 时钟产生:主设备在 SCLK 线上产生连续的时钟脉冲。
  3. 数据移位:在每个时钟周期,主设备通过 MOSI 线发送 1 位数据,同时通过 MISO 线接收 1 位数据。
  4. 传输结束:主设备将 CS 引脚拉高,释放从设备,完成一次数据帧传输。
关键点: SPI 的时钟极性(CPOL)和时钟相位(CPHA)决定了数据采样和输出的具体时序。CPOL 定义时钟空闲时的电平(0 或 1),CPHA 定义数据在时钟的上升沿还是下降沿被采样。两者组合形成四种 SPI 模式(Mode 0~3),驱动开发时必须确保主从设备配置一致。

1.3 全双工通信模式

SPI 最显著的优势之一是其 全双工(Full-Duplex) 通信能力。在同一个时钟周期内,主设备通过 MOSI 发送数据,同时从设备通过 MISO 返回数据,两者互不干扰。

全双工通信的底层原理基于 移位寄存器 结构:

  • 主设备和从设备内部各有一个 8 位(或更多位)的移位寄存器。
  • 两者通过 MOSI 和 MISO 线连接成一个 环形移位回路。
  • 每来一个时钟脉冲,主从双方的寄存器同时左移一位:主设备移出一位到 MOSI,同时从设备移出一位到 MISO。
  • 经过 8 个时钟周期后,主设备的 8 位数据完全移入从设备,同时从设备的 8 位数据完全移入主设备。

下图展示了 SPI 全双工通信的环形移位寄存器结构:

SPI 全双工通信环形移位寄存器结构 SPI 全双工通信 — 环形移位寄存器结构 主设备 (Master) 移位寄存器 (8-bit) 从设备 (Slave) 移位寄存器 (8-bit) MOSI MISO SCLK (时钟由主设备驱动) CS (片选,低电平有效) 全双工通信原理 每个时钟周期,主设备通过 MOSI 发送 1 位,同时从设备通过 MISO 返回 1 位 8 个时钟周期后,主从设备完成 1 字节数据的交换

全双工模式在实际驱动开发中带来的影响:

  • 发送与接收必须成对出现:每次调用 SPI 传输函数时,即使只关心发送数据,也必须提供一个接收缓冲区来接收从设备返回的数据。
  • 虚拟数据:当主设备只希望接收从设备的数据时,必须在 MOSI 线上发送虚拟字节(通常为 0x00 或 0xFF)来产生时钟脉冲。
  • 性能优势:相比 I²C 的半双工模式,SPI 的全双工特性使吞吐量翻倍,特别适合高速数据采集和实时控制场景。
常见误区: 初学者常误以为 SPI 可以像 UART 那样只发送不接收。实际上,由于 SPI 的时钟由主设备产生,从设备无法主动发起传输。即使主设备只发送数据,MISO 线上仍然会有从设备返回的数据,驱动必须处理这些数据,否则可能导致接收缓冲区溢出。

1.4 SPI 总线拓扑结构

SPI 总线支持两种常见的拓扑连接方式:

拓扑类型 连接方式 优点 缺点
独立片选 每个从设备独占一根 CS 线,SCLK/MOSI/MISO 共享 从设备完全独立,支持任意数量 占用主设备 GPIO 引脚较多
菊花链 从设备的 MISO 连接到下一个从设备的 MOSI,共享 CS 节省 GPIO 引脚 延迟累积,传输效率降低,驱动复杂

在嵌入式 Linux 驱动开发中,独立片选 是最常用的拓扑方式,每个从设备在设备树中作为一个独立的 SPI 子节点注册,驱动框架天然支持这种结构。