SPI
1. SPI 的核心特点:高速、全双工
SPI 最大的特点就两个字:快。
- I2C:通常 400kHz(最快几 MHz)。
- SPI:轻松达到 10MHz - 50MHz 甚至更高(比如用来驱动 TFT 屏幕、读写 SD 卡、Flash 芯片)。
它之所以快,是因为它不搞那些“握手、应答、寻址”的复杂动作,直接由**主机(Master)**强行驱动时钟,推着数据走。
2. 四根线的作用
标准 SPI 通常需要 4 根线(I2C 只要 2 根):
- SCK (Serial Clock):时钟线。
- 由主机产生。主机敲一下鼓,大家就传一位数据。
- MOSI (Master Output Slave Input):
- 主机发,从机收的数据线。
- MISO (Master Input Slave Out):
- 从机发,主机收的数据线。
- 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 (串口) | I2C | SPI |
|---|---|---|---|
| 线数 | 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 就是一个**“暴力传输”**协议:
- 拉低 CS:指定你要和谁说话。
- 开始时钟:主机疯狂打拍子。
- 数据交换:主机的数据冲向从机,从机的数据冲向主机(不想发也要发个 0x00 或 0xFF 去把数据换回来)。
- 拉高 CS:结束。