SPI协议基础:从四根线理解Linux SPI框架

1. What is SPI?

在开始本章之前,先抛出一个问题,Linux SPI 框架最终要控制什么?

在嵌入式系统中,核心就是CPU,只有CPU是不能工作的,往往还需要接入各种外设并且与外设通信。
例如传感器、Flash、显示屏、ADC等。不同设备之间需要一种统一的数据交换方式,因此产生了各种通信协议,例如 UART、I2C、SPI。
本系列就是介绍其中的SPI。

先给出定义:SPI(Serial Peripheral Interface)是一种高速全双工同步串行通信协议。

这里针对三个关键点分别解释:

1. 高速

高速是一个模糊概念,究竟高到什么程度?这里高速相对于IIC,普通UART,CAN等低速总线。本身并没有规定最高速度。
其传输数据的速率和SPI的时钟频率有关:

SPI 时钟 理论位速率
1 MHz 1 Mbit/s
10 MHz 10 Mbit/s
20 MHz 20 Mbit/s
50 MHz 50 Mbit/s
100 MHz 100 Mbit/s

2. 全双工

与之对应的还有两个概念:单工和半双工。
画个图大家就清楚了:

  • 单工:数据始终只能单向传输

  • 半双工:同一时间只允许向一个方向传输

  • 全双工:同一个时刻允许两台同时进行双向数据传输

3. 同步串行

很明显,分两部分理解。

先看串行,就是数据一位一位的传输。例如传输数据为一个字节:10110010。
串行通信只能使用一根数据线。每个时刻只能传输一位。
与之对应的为并行,如果使用八根传输线,同一个时刻能传输一个字节。

再看同步,现在数据线上有数据了,那我接收的时候怎么确定什么时候开始读取呢?
又怎么知道每一位持续多长时间?
同步通信通过一根时钟线解决这个问题,就像打电话的铃声,通知你该接电话了。

时钟信号如上,我们只需要规定数据在哪个时钟边沿发生变化,以及在哪个时钟边沿被读取就行。


2. Why Need SPI?

通过上面的讲解,我觉得大家应该知道SPI是个什么东西了。那为什么需要这个东西?不是还有其他协议吗?你SPI就特殊些?就只有你能干了?

其实不是,众多协议中没有一种是最优的。只是每种协议都有自己的偏向性,SPI 是其中偏向”短距离、高速度、简单直接”的方案。

SPI通常由四根线组成,分别为:

  • SCLK:时钟
  • MOSI:主机发、从机收
  • MISO:从机发、主机收
  • CS:片选

只要主机选中设备就能进行传输。

那为什么不用UART代替呢?UART 适合两个设备进行简单的点对点通信,对速率要求不高。

那为什么不用IIC代替呢?IIC只需两个引脚,牺牲了物理那么软件实现就相对复杂。

  • 设备多、速度低、希望省线就选 I²C
  • 设备少、数据多、追求速度就选 SPI

其他协议主播还没工程经验,就不讲了,后面有了再补充。


3. SPI 物理结构

接下来让我们看一下SPI的物理结构。上面其实已经讲了,SPI一般由四根线组成:

  • SCLK:时钟
  • MOSI(Master Output Slave Input):主机发、从机收
  • MISO(Master Input Slave Output):从机发、主机收
  • CS:片选

但有的时候会有5根的情况,是增加了一条 READY 线。之所以需要是因为SPI有一个限制:只有主机可以产生时钟,从机不能主动发起 SPI 传输。
假设从机完成了一次数据采集,想把数据发给主机。它不能直接通过 MISO 发送,因为此时没有 SCLK。上面我们已经说过SCLK的作用和重要性了。此时就需要这根线去通知主机,在两边做约束。

那什么时候需要 READY 呢?如果从机只需要被主机查询,用标准四根线;如果从机需要及时通知主机”我有事/有数据/准备好了”,通常加一根 READY/IRQ,使用五根线。

我们思考一个场景,假设主机产生信号,告诉从机你马上响应我的需求,如果这个时候从机能立马响应且完成需求,那么4根线也没什么关系。如果不能立刻响应,那么主机就需要轮询地问”你好了吗?你好了吗?快点,你好了吗?”

轮询会造成什么恶果呢?一个是占用CPU,一个是响应延迟。那么此时 READY 线就有用了。


4. SPI 通信时序

4.1 通信模式

简单的讲就是两边共同的约定。主要有4种模式 Mode0~3,由两个参数决定:CPOL 和 CPHA。

CPOL(时钟极性):表示不通信时,SCLK 保持高电平还是低电平。

  • 当 CPOL = 0 时,空闲电平为低

  • 当 CPOL = 1 时,空闲电平为高

CPHA(时钟相位):一个时钟周期中,在哪个边沿采样数据。

  • 当 CPHA = 0 时,每个周期的第一个边沿采样
  • 当 CPHA = 1 时,每个周期的第二个边沿采样

4.2 实例

我们以一个实际的例子讲解通讯过程中的时序图。
假设主机要读取从机 0x12 寄存器,从机返回数据 0x5A。

两边做一下规定:

  • 使用 SPI Mode 0,即 CPOL=0,CPHA=0
  • 8位数据
  • MSB first,高位先传
  • 读命令最高位为1
  • 寄存器地址为 0x12
  • 主机发送命令 0x80 | 0x12,由操作码和寄存器地址组成
  • 主机再发送一个 Dummy 字节 0xFF,为从机返回数据提供时钟

整个数据链:

第一字节 第二字节
主机发送 0x92 0xFF
从机返回 无效 0x5A

整个时序图如下:

主机先拉低CS,选中从机。根据设置的 Mode0,在每个周期的第一个边沿采样数据。
产生8个时钟,在MOSI上发送 0x92,发送完成后,接着发送 0xFF 为从机提供时钟,从机收到 0x92 的信息去寄存器 0x12 取数据,在MISO上返回 0x5A。

4.3 为什么 Linux 需要 SPI 框架

为什么Linux需要一个统一的SPI框架?现实的场景往往不是一个MCU对应一个固定的SPI,而是不同厂商不同类型的SPI外设。而SPI框架的作用就是把控制器怎么工作和外设需要传输什么数据分离,并统一管理。

整个框架如下,先大致了解一下,后面会详细介绍:

  • Device Driver:决定具体的通信设备是什么
  • SPI Core:负责管理每次的SPI通信请求
  • SPI Controller Driver:负责具体的硬件操作,比如使用什么模式、数据的传输宽度、SPI寄存器配置等
  • Hardware:具体硬件

5. 总结

SPI是一种同步串行通信协议,通过SCK、MOSI、MISO、CS四根信号线实现Master和Slave之间的数据交换。

在Linux系统中,SPI硬件被抽象为SPI Controller,而具体外设被抽象为SPI Device。Linux SPI Framework通过SPI Core连接Controller Driver和Device Driver,使设备驱动无需关注底层寄存器操作,只需要调用统一SPI接口即可完成数据传输。


6. 互动

你现在能回答下面四个问题吗?欢迎在评论区交流讨论:

  1. SPI数据谁产生?
  2. Linux SPI驱动框架里面谁对应Master?
  3. 为什么需要Linux SPI驱动框架?

SPI协议基础:从四根线理解Linux SPI框架
https://cj0510.github.io/2026/08/01/Linux Kernel/SPI/SPI协议基础/
作者
CJ1018
发布于
2026年8月1日
许可协议
CC BY-NC-SA 4.0