SPI协议基础:回顾SPI的4线制、主从模式、数据交换原理

讲QSPI之前,咱们得先把老祖宗SPI搞透彻。我见过太多工程师上来就调QSPI,结果连最基本的时钟极性相位都没弄明白,花了一整天查波形,最后发现是片选时序记错了。

SPI全称Serial Peripheral Interface,说白了就是一根时钟线加几根数据线,主设备带着从设备玩。它不像I2C那样需要地址仲裁,谁主谁从一清二楚,硬件设计上也简单不少。

四线制:名字就叫“串行外设接口”

标准的SPI就四根线,但有些人会加第五根、第六根,咱们先看基本款:

信号名 全称 方向 作用
SCLK Serial Clock 主→从 时钟脉冲,决定数据采样的节奏
MOSI Master Out Slave In 主→从 主设备发送数据给从设备
MISO Master In Slave Out 从→主 从设备发数据回主设备
CS/SS Chip Select / Slave Select 主→从 片选信号,低电平有效,选中从设备

个人习惯:我画原理图时,会在CS信号上加个上拉电阻。有一次调试新板子,CS悬空时电平不定,从设备一直乱响应,查了两天才发现。后来每块板子我都习惯性加10kΩ上拉到VCC。

嗯,这里要注意:片选信号一旦拉低,从设备就得准备好接收/发送数据。如果片选在传输过程中被拉高,从设备会立刻终止当前操作——这个行为不同芯片有差异,有的甚至会清空FIFO。

主从模式:谁发时钟谁就是主

SPI通信里只有主设备能产生时钟,从设备永远被动。你想想看,如果两个设备都想发时钟,那波形不就打架了吗?所以硬件设计时,所有从设备的SCLK和MOSI都得连到主设备的同一组引脚上,MISO可以并联(前提是从设备输出是三态的),但片选信号必须独立。

我曾经遇到一个新手,把两个SPI从设备的MISO直接连一起,没考虑高阻态。结果主设备读数据时,两个从设备同时输出,总线冲突,波形全乱了。避坑指南:**多从设备共用MISO时,必须确保未选中从设备的MISO输出为高阻态。** 很多从设备手册里会写“DOUT is high-impedance when CS is high”,设计前一定要确认。

数据交换原理:同时移位,同时采样

SPI的数据交换是同时进行的。主设备在时钟沿上把MOSI上的数据移出去,同时从设备在同一个时钟沿把MISO上的数据移回来。说白了就是一个移位寄存器循环。为什么能做到全双工?因为用了两根独立的数据线,收发互不干扰。

来看一个典型的8位数据交换时序:

// 伪代码示意:主设备发送0x55,从设备返回0xAA
// 假设时钟极性为0(空闲低),相位为0(第一个沿采样)
CS = 0;
for (i = 0; i < 8; i++) {
    MOSI = (0x55 << i) >> 7;   // 从高位开始逐位送出
    SCLK = 1;                     // 上升沿采样
    bit_in = MISO;                // 读入从设备送出的位
    SCLK = 0;                     // 下降沿变化数据
    rx_data = (rx_data << 1) | bit_in;
}
CS = 1;

我个人喜欢用示波器抓这四根线来看时序,尤其注意CS拉低之后到第一个时钟沿的建立时间。很多芯片要求CS拉低后至少等几个ns才能开始发时钟,如果MCU跑得太快,从设备可能来不及准备。

SPI工作的核心逻辑图

下面这张图展示了SPI在一次传输中的完整流程,从CS拉低到数据移位再到CS拉高。

SPI单次传输流程(主设备视角) 主设备拉低CS 选中从设备 主设备准备 发送/接收数据 主设备产生 SCLK脉冲序列 逐位交换数据 MOSI/MISO移位 所有位传完? (8/16/32 bit) 拉高CS 释放从设备 否 在整个传输过程中,MISO和MOSI在每个时钟沿同时移出一位并移入一位 位顺序通常MSB first(最高位在前),但有些设备可以配置为LSB first

SPI的四种模式(时钟极性与相位)

这部分是调试时最容易踩坑的地方。你想想看,主设备和从设备到底在时钟的哪个沿采样数据?这个‘约定’就叫极性(CPOL)和相位(CPHA)。

  • CPOL(Clock Polarity):空闲时时钟电平是高还是低。0表示空闲低,1表示空闲高。
  • CPHA(Clock Phase):数据采样发生在第一个还是第二个时钟沿。0表示第一个沿采样,1表示第二个沿采样。

组合起来就是大家常说的模式0~3:

模式 CPOL CPHA 采样沿 数据变化沿
0 0 0 上升沿 下降沿
1 0 1 下降沿 上升沿
2 1 0 下降沿 上升沿
3 1 1 上升沿 下降沿

我曾经踩过的坑:一个项目里用SPI驱动AD7190,手册上写的是CPOL=1, CPHA=1。结果我把模式配成了0,数据读回来全是错的。拿示波器一看,采样沿正好比正确相反,读到了数据变化中间的不稳定区域。所以**新板子到手第一件事,先看从设备手册,确认支持的模式**。如果支持多模式,我习惯默认用模式0,因为大多数MCU的SPI外设默认就是模式0。

实际通信中的几个重要时序参数

除了CPOL/CPHA,还有几个参数决定了通信能否稳定跑在高速下:

  • SCLK频率:主设备时钟不能超过从设备支持的最大速率。我试过把STM32的SPI时钟配到40MHz,结果接了一个只支持20MHz的Flash,每隔几个字节就丢数据。
  • CS建立时间:CS拉低到第一个SCLK边沿的最短时间。有些从设备需要至少50ns,高速MCU如果不加延时,数据根本传不过去。
  • CS保持时间:最后一个SCLK边沿到CS拉高的最短时间。同理,太短了可能导致从设备没完成存储操作。
  • 数据有效时间:时钟沿前后数据必须保持稳定的窗口。这个一般由从设备决定,主设备只要时序满足就没问题。

快速调试口诀:

  • 先看空闲时钟电平(CPOL)——采集波形看CS拉高后SCLK是0还是1。
  • 再看采样沿位置(CPHA)——在第一个时钟沿采还是在第二个。
  • CS信号重点关注建立/保持时间,尤其是在高速下。

嗯,SPI基础部分就先聊到这儿。模式怎么选、时序怎么调,后面讲QSPI相位极性时会反复用到这些概念。你先消化一下,尤其是那张流程图和模式表,很多问题都能从那里找到答案。