四线接口:CLK、DO、DI、CS
四条线:
- CLK 时钟线
- DO 数据输出(主从视角下也常对应 MOSI)
- DI 数据输入(主从视角下也常对应 MISO)
- CS 片选(每个设备一条,独享)
与 I2C、UART 的对比
| 特性 | SPI | I2C | UART |
|---|---|---|---|
| 同步/异步 | 同步(有时钟线) | 同步(有时钟线) | 异步(无时钟线) |
| 通信线数 | 4线(CS/CLK/DO/DI) | 2线(SCL/SDA) | 2线(TX/RX) |
| 多设备 | CS 独享,CLK/DO/DI 共用 | 地址选择 | 点对点 |
| 传输特点 | 发送 N 字节必接收 N 字节 | 主控控制读写 | 全双工独立 |
| 速度 | 高速(MHz 级) | 中速(100k–400k–1M) | 低速(波特率限制) |
| 适用场景 | Flash、高速传感器 | EEPROM、传感器 | 调试、通信模块 |
同步/异步:有时钟线时,可以精准地知道何时读取数据,不需要约定波特率、误差也不会累积,所以速度快,这就是同步通信。否则只能异步通信,速度会慢。
CS 独享:每个设备都有单独的一根 CS 线。和 I2C 不同,I2C 通过软件协议尽量复用连接线(地址广播),SPI 则是通过硬件解决,减少了协议开销,可以满足更高的速度要求。
发送 N 字节必接收 N 字节:这是硬件上的限制,软件上可以读取但忽略、发送假数据,但是硬件上 SPI 被设计成了时钟由发送动作产生——不发送就没有时钟,也就不能接收。
CPOL / CPHA 与四种模式
四种模式通过两个开关组合而来:
- CPOL(Clock Polarity,时钟极性):空闲时时钟电平。CPOL=0 平时为低电平,CPOL=1 平时为高电平。
- CPHA(Clock Phase,时钟相位):在第几个边沿采样。CPHA=0 为第一个边沿,CPHA=1 为第二个边沿。
| 模式 | CPOL | CPHA | 时钟空闲 | 采样边沿 |
|---|---|---|---|---|
| Mode 0 | 0 | 0 | 低电平 | 上升沿(第 1 个) |
| Mode 1 | 0 | 1 | 低电平 | 下降沿(第 2 个) |
| Mode 2 | 1 | 0 | 高电平 | 下降沿(第 1 个) |
| Mode 3 | 1 | 1 | 高电平 | 上升沿(第 2 个) |
为什么需要多种模式? 不同的设备有不同的数据输出时序要求:如果数据在时钟边沿前就准备好,就用 CPHA=0;如果数据在时钟边沿后才稳定,就用 CPHA=1。
若数据在上升沿前已稳定,常用 Mode 0 或 Mode 3;若在下降沿前已稳定,常用 Mode 1 或 Mode 2。
状态位:TXE 与 RXNE
- TXE(Transmit Buffer Empty):TX buffer 空,可以写数据
- RXNE(Receive Buffer Not Empty):RX buffer 非空,可读
三种传输方式
和 I2C、UART 一样,HAL 库也提供了查询、中断、DMA 三种方式。
核心函数
HAL_SPI_TransmitReceive— 同时发送和接收HAL_SPI_Transmit— 仅发送HAL_SPI_Receive— 仅接收