通信协议篇三:SPI 通信原理详解之时钟模式、时序与W25Q32示例

SPI 是嵌入式开发里最常见的高速串行总线之一。相比 I2C 和 UART,SPI 结构更直接、速度更高,也更适合和 Flash、ADC、DAC、显示屏等板级外设通信。本文从底层原理时钟模式通信时序W25Q32 读 ID 实验,系统讲清 SPI 到底是怎么工作的。

ℹ️ 一句话先讲清楚:SPI(Serial Peripheral Interface,串行外设接口)是最早由摩托罗拉(Motorola)提出的一种高速、同步、全双工、主从式串行通信协议,常用于 MCU 与 Flash、ADC、DAC、显示屏、传感器等外设之间进行板级数据交换。

一、SPI 是什么

SPI 的典型特点可以直接概括为:

  • 速度高:常见工作频率为 几 MHz 到几十 MHz
  • 协议简单:无地址、无统一 ACK、无总线仲裁
  • 全双工:主从可在同一时钟下同时收发数据
  • 片选通信:通过 CS/SS 选择目标从设备

SPI 通常采用单主多从结构:

  • 主设备负责发起通信
  • 主设备负责提供时钟 SCLK
  • 从设备在主设备给出的时钟下完成数据输入与输出
  • 多个从设备通常共享时钟线和数据线,靠不同的片选线区分

SPI 常用于 MCU 与 Flash、ADC、DAC、显示屏、传感器等外设之间进行板级数据交换,特别适合以下场景:

  • 屏幕刷新
  • Flash 连续读写
  • ADC / DAC 数据搬运
  • 高频率寄存器访问
  • 板内短距离高速通信

常见连接如下。

SPI连接原理图
SPI连接原理图

四根核心信号线分别是:

  1. SCLK(Serial Clock):主设备输出的同步时钟
  2. MOSI(Master Out Slave In):主发从收
  3. MISO(Master In Slave Out):主收从发
  4. CS / SS(Chip Select / Slave Select):片选信号,通常低电平有效

拓展来看,某些器件也支持 Daisy Chain(菊花链)。多个从机串联,时钟与片选共用,数据按链式依次传递,常见于移位寄存器、LED 驱动器等。

其特点是:

  • SCLK / MOSI / MISO 共用
  • 每个从机独立使用一根 CS
  • 任意时刻通常只选中一个从机

二、SPI 通信原理及示例

2.1 底层原理

SPI 的核心思想是:每个设备内部都有一个移位寄存器,可以用来发送或接收一个字节的数据。这两个移位寄存器首尾相连,形成一个环,一个寄存器的输出接到另一个寄存器的输入,反过来也一样。其中一方作为主机,负责控制公共时钟信号,确保当一侧移出 1 位时,另一侧也恰好同步移入 1 位。SPI 的底层原理几乎已经简单到不能再简单了。
SPI 不是单向发射器,而是同步移位交换器。

image-20260406124113415
image-20260406124113415

大多数 SPI 外设默认使用 MSB First,主从双方位序必须一致,否则数据就会错位。

每来一个时钟:

  • 主机向 MOSI 移出 1 位
  • 从机采样 MOSI 上的 1 位
  • 从机向 MISO 移出 1 位
  • 主机采样 MISO 上的 1 位

重复 8 次,就完成 1 个字节交换。

💡 底层本质

SPI 的本质就是两个移位寄存器在同一时钟下同步移位。也正是这种简单性,让 SPI 具有很高的速度。异步串口通信通常工作在几十万 bit/s 量级,而 SPI 往往可以达到 10 Mbit/s 甚至更高

2.2 SPI 的四种时钟模式

上面讲的是 SPI 如何在时钟驱动下完成一位一位的数据交换,而要想让主机和从机在正确的时刻发送、在正确的时刻采样,就必须进一步约定时钟的空闲状态以及在哪个边沿采样数据,这就是 SPI 的时钟模式。

  • CPOL(Clock Polarity):时钟空闲电平
  • CPHA(Clock Phase):数据在第几个边沿采样

记忆方法可以直接记:

  • CPOL 管空闲高低
  • CPHA 管第几个边沿采样

四种模式如下:

模式 CPOL CPHA 空闲电平 采样边沿
Mode 0 0 0 上升沿采样
Mode 1 0 1 下降沿采样
Mode 2 1 0 下降沿采样
Mode 3 1 1 上升沿采样

之所以有这 4 种模式,本质上是为了兼容不同器件内部的数据输出与锁存时序,确保“数据变化边沿”和“数据采样边沿”能够错开,留出足够的时序裕量。

通常可以从芯片厂商手册中找到对应的时钟模式说明:

W25Q32时钟模式
W25Q32时钟模式

⚠️ 注意:SPI 通信失败最常见的问题之一,就是主从双方 CPOL / CPHA 或位序配置不一致。

2.3 SPI 通信时序

SPI 通信的核心逻辑其实很直接:

  1. 主机先选择目标从机(拉低对应 CS
  2. 主机输出时钟 SCLK
  3. 主机和从机按照时钟同步移位
  4. 主机从 MOSI 发数据给从机
  5. 从机同时通过 MISO 回数据给主机
  6. 一帧结束后,主机释放 CS

可简化理解为:

CS拉低 -> 时钟开始 -> 双方边移位边采样 -> 传完一帧 -> CS拉高

2.3.1 用一次 W25Q32 读 ID 看懂 SPI 通信

以 W25Q32 的 0x9F 读 JEDEC ID 为例,下面这段代码就是一次完整的 SPI 通信。

手册说明文档:C179173_5BBD793D2D7B3672E140BC7AE85C11FF.pdf (szlcsc.com)

image-20260406125116397
image-20260406125116397

这里使用 MicroPython + ESP32-C3,因为实验起来比较简单。本例使用的是 SPI Mode 0(CPOL=0,CPHA=0)

from machine import Pin, SPI
import time

cs = Pin(4, Pin.OUT)
cs.value(1)

spi = SPI(1,
          baudrate=200000,
          polarity=0,
          phase=0,
          sck=Pin(2),
          mosi=Pin(3),
          miso=Pin(10))

def read_id():
    cs.value(0)
    time.sleep_us(5)

    spi.write(b'\x9F')
    data = spi.read(3)

    time.sleep_us(5)
    cs.value(1)
    return data

从波形上看,几个关键引脚可以这样对应:

  • CS:低电平包住整次事务
  • SCLK:每传 1 位就会有 1 个时钟脉冲
  • MOSI:先看到命令 0x9F,后面通常是 3 个占位字节
  • MISO:命令阶段往往没有有效返回,随后输出 3 个 ID 字节

在逻辑分析仪里看波形,通常可以对应成:

CS 拉低 -> MOSI 发命令 -> 主机继续发 dummy -> MISO 回数据 -> CS 拉高

SPI时序
SPI时序

单次 SPI 通信可以拆成 6 步:

  1. CS 拉低:选中 W25Q32,本次通信开始
  2. MOSI 发送 0x9F:主机发出“读取 JEDEC ID”命令
  3. SCLK 输出 8 个时钟:从机在这些时钟下接收命令
  4. 主机继续发送 3 个 dummy byte:底层就是 spi.read(3) 期间主机继续打时钟
  5. MISO 返回 3 个 ID 字节:例如厂商 ID、存储类型、容量信息
  6. CS 拉高:本次通信结束

第二步:主机发送 0x9F 命令,对应的逻辑分析仪与示波器波形如下:

示波器显示MOSI发送0X9F
示波器显示MOSI发送0X9F

逻辑分析仪主机发送0X9F
逻辑分析仪主机发送0X9F

📋 关键结论

  • SPI 不是“请求-响应”,而是一边发,一边收
  • 主机每发 1 位的同时,也会同步收到 1 位
  • SPI 没有真正的“只读”操作,所谓“读”,本质上是主机发送占位数据,再把从机的数据换回来
💡 dummy byte 是什么?

dummy byte 就是占位字节。它本身通常没有业务含义,作用只是让主机继续产生时钟,好让从机把数据从 MISO 推出来,常见取值是 0x000xFF

三、SPI 优点与局限

SPI 的主要优点:

  • 无起始位和停止位开销:片选有效期间可连续传输数据,适合流式交换
  • 协议简单:无统一地址、无仲裁、无固定 ACK 机制,总线控制直接
  • 速率高:常见工作频率可达几 MHz 到几十 MHz,通常高于 I2C
  • 支持全双工MOSIMISO 分离,可在同一时钟下同时发送和接收
  • 帧宽灵活:常见为 8 位,也可支持 16 位、32 位或连续流式传输
  • 硬件实现直接:从机使用主机提供的时钟,不需要像 UART 那样做独立时钟恢复

SPI 的主要局限:

  • 信号线较多:标准四线 SPI 至少需要 SCLKMOSIMISOCS,多从机还需要更多片选线
  • 无总线级接收确认:不像 I2C 那样有统一 ACK/NACK 机制
  • 无统一错误检测机制:总线层通常没有奇偶校验、CRC、重传、仲裁等标准机制
  • 通常采用单主结构:工程上最常见的是单主多从
  • 不适合长距离通信:更适合 PCB 板内或短距离连接
  • 器件协议差异大:不同芯片的命令格式、时序要求和返回规则往往不统一

四、SPI 与 I2C / UART / CAN 对比

接口 关键特点 典型场景
SPI 高速、全双工、靠片选、线较多 板级高速外设通信
I2C 省线、地址寻址、适合多器件 低速传感器、EEPROM
UART 异步、点对点、实现简单 调试串口、模块通信
CAN 高可靠、多节点、支持仲裁 工业控制、汽车电子

SPI 常用于高速外设通信,原因也很直接:它没有地址仲裁、逐字节 ACK 这类额外开销,又通常用于板内短距离连接,所以更容易做到更高频率。

  • UART 常见在 115200bps1Mbps 左右
  • I2C 常见在 100kHz400kHz1MHz
  • SPI 常见在 1MHz10MHz20MHz40MHz

一句话概括:

  • SPI:快、简单、全双工,但线多
  • I2C:省线、适合多器件,但速度较低
  • UART:最简单,适合点对点异步通信
  • CAN:强调可靠性和多节点仲裁

五、速记版与总结

📋 速记版

  • 主机提供时钟,控制整个通信节奏
  • MOSI / MISO 支持同时发送和接收
  • CS 用于选择目标从机
  • CPOL / CPHA 决定时钟模式
  • SPI 本质上是移位寄存器在时钟驱动下做同步交换

如果只记住一句话,那就是:SPI 是一种面向板级高速外设通信的同步、全双工、主从式串行接口,特点是快、直接、灵活,但线多且更依赖具体器件手册。


六、常见问题与速答

SPI 调不通时,优先检查这几类问题:

  • 片选时序错误:常见现象是芯片无响应、数据错位、命令执行失败;重点看 CS 是否正确拉低、整帧期间是否保持有效、拉高时机是否符合手册要求
  • 模式或位序不匹配:常见现象是有波形但数据不对;重点看 CPOL / CPHA 是否一致,以及主从双方是否都使用 MSB FirstLSB First
  • 读操作忘记发送 dummy:SPI 读数据时主机必须继续提供时钟,因此通常要发送空字节来换取从机返回数据
  • 多从机 MISO 冲突:多个从机共用 MISO 时,必须保证只有被选中的从机驱动 MISO,其他从机处于高阻态
  • 频率过高导致不稳定:可能出现偶发错码、固定字节异常、波形边沿不干净等问题;工程上通常先降频验证,再逐步提高频率
Q:SPI 是什么?

SPI 是一种同步、全双工、主从式串行通信协议。主机通过时钟线控制通信节奏,通过 MOSI 和 MISO 实现数据交换,通过片选线选择目标从机。它常用于 MCU 与 Flash、显示屏、ADC、传感器等高速外设之间的板级通信。

Q:SPI 为什么比 I2C 快?

因为 SPI 有独立时钟线,没有地址仲裁和逐字节 ACK 这类额外开销,通常又用于短距离板级通信,所以更容易工作在更高频率下。

Q:SPI 为什么需要片选线?

因为 SPI 通常没有地址机制。多个从机共享总线时,主机需要通过片选线明确指定本次通信的目标设备。

Q:SPI 四种模式怎么理解?

SPI 四种模式由 CPOL 和 CPHA 组合而来。CPOL 决定时钟空闲电平,CPHA 决定数据在第几个边沿采样。主从双方模式必须一致,否则容易出现采样错误。

Q:SPI 读数据时为什么还要发送数据?

因为 SPI 是时钟驱动的同步移位通信。从机不会主动输出数据,主机必须继续提供时钟,因此通常要发送 dummy byte 来换取从机返回的数据。