2. SPI 协议基础与时序

2.1 为什么 QSPI 还要从 SPI 讲起?

很多人觉得 SPI 简单,四个信号线一接就能跑数据。我在项目里见过不少新手上来就调 QSPI,结果死活读写不正常,最后发现是 SPI 最基本的时钟极性和相位没搞对。你说冤不冤?

QSPI 本质上是 SPI 的扩展——多了一根数据线变成了四根,但控制逻辑、时序约束、主从关系,全都从 SPI 继承下来。所以想把 QSPI Flash 引导搞明白,先得把 SPI 的底裤看穿。

核心观点: QSPI = SPI 的并行版本。SPI 的每一个时序细节,都在 QSPI 里原封不动地保留了。

2.2 SPI 总线:四根线的故事

标准 SPI 有四个信号,你肯定背得出来:

  • SCLK(Serial Clock)—— 主设备产生的时钟,决定传输速率
  • MOSI(Master Out Slave In)—— 主设备发,从设备收
  • MISO(Master In Slave Out)—— 主设备收,从设备发
  • CS(Chip Select)—— 片选,低电平有效

嗯,注意 CS 是低有效。我见过有人把这个搞反,然后折腾了一整天。

还有个东西叫 SS(Slave Select),和 CS 是同一个意思。不同的芯片手册叫法不一样,别被绕晕。

2.3 时钟极性和相位:CPOL 和 CPHA

这才是 SPI 最容易踩坑的地方。

模式 CPOL CPHA 时钟空闲电平 数据采样沿
Mode 0 0 0 低电平 上升沿
Mode 1 0 1 低电平 下降沿
Mode 2 1 0 高电平 上升沿
Mode 3 1 1 高电平 下降沿

QSPI Flash 绝大多数都工作在 Mode 0。我建议你拿到新芯片时,第一件事就去翻数据手册里的时序图,找到 CPOL 和 CPHA 的约定,否则连 Read ID 都读不出来。

我曾经在一个项目里把主控的 SPI 配成了 Mode 3,Flash 芯片支持 Mode 0 和 Mode 3,但那个国产 Flash 的数据手册写得不清楚。结果读出来的 JEDEC ID 一直 0xFF,折腾两周才发现是时钟极性配反了……嗯,从那以后我每次建项目第一件事就是配 SPI 模式。

2.4 SPI 传输时序:一帧数据怎么走?

简单来说,一个 SPI 传输由以下步骤组成:

  1. 拉低 CS —— 通知从设备:我要跟你通信了
  2. 发送时钟 + 数据 —— 每来一个时钟沿,主从各移出一位数据,同时锁存一位数据
  3. 拉高 CS —— 结束本次传输

注意 SPI 是全双工的。你可以想想看:主设备发一个字节出去的同时,从设备也在发一个字节回来。所以 SPI 的每一笔传输,其实都是同时收发的。

举个例子,你要从 Flash 读数据:

  • 主设备先发命令字节(比如 0x03 读命令)
  • 紧接着发地址字节(通常是三字节地址)
  • 然后主设备继续发 dummy 字节(0x00),从设备在 MISO 上返回数据

实际上,主设备发 dummy 字节的同时,从设备才把数据送出来。这个过程没有“空闲”,每一拍都有数据流动。

2.5 SPI 的关键时序参数

别光看频率,别的参数也重要。我列出几个必须关注的:

参数 含义 典型值(SPI Flash)
f_SCK 最大时钟频率 50 MHz~104 MHz(QSPI 更高)
t_SU 数据建立时间 几 ns
t_H 数据保持时间 几 ns
t_CSH CS 撤销到下一帧 CS 有效的时间 几十 ns
t_CLQV 时钟到数据输出有效时间 8~15 ns

我个人习惯是在设计 PCB 时给 SPI 信号线留等长布线,尤其是高频场景(>50 MHz)。不然信号歪了,时序就崩了。

2.6 SPI 与 QSPI 的异同

说白了,QSPI 就是把标准 SPI 的单根数据线变成了两根或四根(分别是 Dual SPI 和 Quad SPI)。

看这个对比表:

特性 标准 SPI QSPI(Quad SPI)
数据线数量 MOSI + MISO(2根) IO0~IO3(4根,双向)
每拍传输位数 1 bit 4 bit
全双工 是 半双工(同一时刻只能发或收)
典型时钟 ≤ 50 MHz ≤ 104 MHz(单倍率)
吞吐率(理论) 50 Mbps 416 Mbps(DDR 模式可更高)

这里有个要点:QSPI 的数据线是双向的。标准 SPI 的 MOSI 和 MISO 是固定方向的,而 QSPI 的 IO0~IO3 在发送阶段是输出,在接收阶段是输入。所以主控和 Flash 之间需要做方向切换,这给软件和硬件都增加了复杂度。

2.7 时序对比:标准 SPI 读 vs QSPI 读

拿读操作来对比最直观。

标准 SPI 读(命令 0x03)

CS#   \____________________________/
SCLK  _¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_
MOSI  [CMD][ADDR] [0x00][0x00]...
MISO  xxxxxxxx  [D0][D1][D2]...

QSPI 读(命令 0xEB,四线模式)

CS#   \____________________________/
SCLK  _¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_¯_
IO0   [CMD][ADDR][D0][D4][D8]...
IO1   [CMD][ADDR][D1][D5][D9]...
IO2   [ADDR][D2][D6][D10]...
IO3   [ADDR][D3][D7][D11]...
// 注意:命令阶段仍只用 IO0,地址阶段用四线,数据阶段四线并行输出

看到差别了吗?QSPI 读操作中,地址和数据都用四根线并行传输,但命令阶段通常还是单线(为了兼容性好)。这样每拍能传 4 位,速度直接翻四倍。

小技巧: 调试 QSPI 时,如果数据读出来全是 0xFF,先检查 CS 是否被正确拉低;如果读出来全是 0x00,检查时钟极性;如果数据错位,检查字节序(MSB first / LSB first)。我个人的“三板斧”屡试不爽。

2.8 SPI 协议核心知识结构图

下面这张图把 SPI 协议的基础要素、时序参数、以及向 QSPI 的延伸画在了一起。你可以把它当作本章的小结。

SPI 协议核心知识结构 SPI 总线协议 四根信号线 SCLK / MOSI MISO / CS# 时钟极性 / 相位 CPOL / CPHA Mode 0~Mode 3 关键时序参数 f_SCK / t_SU / t_H t_CSH / t_CLQV QSPI:四根数据线并行 四线传输 IO0~IO3 双向 半双工 吞吐率更高 4× SPI 速率 DDR 模式再翻倍 方向切换 硬件/软件配合 GPIO 模拟方向 掌握 SPI 基础,QSPI 引导加载就成功了一半

2.9 本章小结

SPI 不是什么高深的东西,但基础不牢地动山摇。你想想看,如果连 CPOL 和 CPHA 都搞错,后面 QSPI 的 DDR 模式就更别想调通。我建议你打开开发板,用逻辑分析仪抓一次 SPI 读 Flash 的波形,对照着这章的内容看一遍,理解会深很多。

记住几个关键点:

  • SPI 是全双工,但 QSPI 是半双工(方向需切换)
  • 大多数 QSPI Flash 默认是 Mode 0
  • 时序参数要关注建立时间、保持时间和 CS 间隔时间
  • QSPI 的每根 IO 线都能在特定阶段当输入或输出