Skip to content

SPI

1. SPI 的核心特点:高速、全双工

SPI 最大的特点就两个字:

  • I2C:通常 400kHz(最快几 MHz)。
  • SPI:轻松达到 10MHz - 50MHz 甚至更高(比如用来驱动 TFT 屏幕、读写 SD 卡、Flash 芯片)。

它之所以快,是因为它不搞那些“握手、应答、寻址”的复杂动作,直接由**主机(Master)**强行驱动时钟,推着数据走。


2. 四根线的作用

标准 SPI 通常需要 4 根线(I2C 只要 2 根):

  1. SCK (Serial Clock):时钟线。
    • 主机产生。主机敲一下鼓,大家就传一位数据。
  2. MOSI (Master Output Slave Input)
    • 主机发,从机收的数据线。
  3. MISO (Master Input Slave Out)
    • 从机发,主机收的数据线。
  4. CS / SS (Chip Select / Slave Select):片选线。
    • 这是 SPI 的灵魂。 I2C 靠地址选人,SPI 靠这根线选人。
    • 平时是高电平。主机把谁的 CS 拉低,谁就开始干活。其他没被拉低的设备就装聋作哑(高阻态)。

3. 最核心的机制:交换(Shift Register)

这是理解 SPI 最最关键的一点,请务必记住:

SPI 的本质不是“发送”和“接收”,而是“交换”。

想象一下,主机和从机内部各有一个 8 位的 圆盘(移位寄存器),这两个圆盘通过 MOSI 和 MISO 连成了一个 闭环传送带

当主机产生 8 个时钟脉冲时,发生的是**“乾坤大挪移”**:

  • 主机的最高位(Bit 7)被推出去,顺着 MOSI 跑到了从机的最低位。
  • 同时,从机的最高位(Bit 7)被推出去,顺着 MISO 跑到了主机的最低位。

后果:

当 8 个时钟结束后,主机里的数据跑到了从机里,从机里的数据跑到了主机里。它们互换了手中的牌。

代码启示:

这就是为什么在 STM32 的 HAL 库或者底层代码中,SPI 的读写通常合并成一个函数:

received_data = SPI_Transfer(send_data);

你想读数据? 你必须先扔出去一个垃圾数据(Dummy Byte,通常是 0xFF 或 0x00),把对方的数据“挤”进来。


4. 只有 SPI 有的麻烦事:4 种模式 (CPOL & CPHA)

I2C 和 UART 的时序基本是固定的,但 SPI 比较随性。它有两个配置项,组合起来就有 4 种模式。如果你连不上设备,90% 是模式选错了。

A. CPOL (Clock Polarity) - 时钟极性

  • CPOL = 0:空闲时 SCK 是 低电平
  • CPOL = 1:空闲时 SCK 是 高电平

B. CPHA (Clock Phase) - 时钟相位

  • CPHA = 0:在 第 1 个 跳变沿(上升或下降)采样数据。
    • 比喻:鼓槌举起来还没敲下去的时候,就要拍照。
  • CPHA = 1:在 第 2 个 跳变沿采样数据。
    • 比喻:鼓槌敲下去的一瞬间拍照。

怎么选?

不用背!直接看从机(传感器/屏幕)的数据手册(Datasheet)里的时序图。

  • 如果图上 CS/SS 拉低时 SCK 是低的,那就是 CPOL=0。
  • 如果数据是在 SCK 的边缘中间变化的,那就是 CPHA=1;如果数据在 SCK 变化前就准备好了,那就是 CPHA=0。
  • (最常用的通常是 模式0 或 模式3)

5. 三大协议终极对比

特性UART (串口)I2CSPI
线数2 (TX, RX)2 (SCL, SDA)4 (SCK, MOSI, MISO, CS)
速度慢 (115200 bps)中 (400 kHz)极快(几十 MHz)
通信方式异步 (靠波特率)同步 (半双工)同步 (全双工)
多设备点对点 (通常)地址区分CS引脚区分
流控无 (容易丢包)有 (ACK应答)无 (发了就不管,不论死活)
应用场景打印调试、GPS传感器、EEPROM屏幕(LCD)、SD卡、Flash

6. 总结

SPI 就是一个**“暴力传输”**协议:

  1. 拉低 CS:指定你要和谁说话。
  2. 开始时钟:主机疯狂打拍子。
  3. 数据交换:主机的数据冲向从机,从机的数据冲向主机(不想发也要发个 0x00 或 0xFF 去把数据换回来)。
  4. 拉高 CS:结束。