3. SPI协议详解
SPI(Serial Peripheral Interface)是飞控系统中最常用的板级高速同步串行总线之一。它由 Motorola 提出,采用主从架构、全双工同步传输,典型速率可达 1~50 MHz,远高于 I²C。飞控中常见的 IMU、气压计、磁力计、Flash、SD 卡、无线模块等大量使用 SPI 接口。理解 SPI 的物理层、时序模式与片选拓扑,是编写稳定传感器驱动的前提。
一、物理层:四根信号线的职责
标准 SPI 使用四根信号线,构成一个主设备与一个或多个从设备之间的同步通信链路:
- SCLK(Serial Clock):由主机产生的时钟,决定数据传输速率,所有数据在时钟边沿采样或移出。
- MOSI(Master Out Slave In):主机输出、从机输入,主机通过它向从机发送命令与数据。
- MISO(Master In Slave Out):从机输出、主机输入,从机通过它回传数据。多从机时 MISO 通常为高阻态共享。
- CS/SS(Chip Select / Slave Select):片选信号,低电平有效,主机拉低某个从机的 CS 才与其通信。
SPI 没有像 I²C 那样的地址机制,也没有硬件应答(ACK)。从机选择完全依赖片选线,因此“一主一从”至少需要 4 根线,“一主多从”则需要为每个从机单独引出一根 CS,或采用菊花链方式共享 CS。
二、时序图与模式 0-3
SPI 的时序由两个参数决定:CPOL(Clock Polarity,时钟极性)和 CPHA(Clock Phase,时钟相位)。二者组合形成四种模式(Mode 0~3),主从双方必须使用相同模式,否则数据错位。
- CPOL=0:空闲时 SCLK 为低电平;CPOL=1:空闲时 SCLK 为高电平。
- CPHA=0:在第一个时钟边沿采样数据;CPHA=1:在第二个时钟边沿采样数据。
| 模式 | CPOL | CPHA | 空闲电平 | 采样边沿 | 典型器件 |
|---|---|---|---|---|---|
| Mode 0 | 0 | 0 | 低 | 上升沿 | 多数 IMU、Flash |
| Mode 1 | 0 | 1 | 低 | 下降沿 | 部分 ADC |
| Mode 2 | 1 | 0 | 高 | 下降沿 | 少数传感器 |
| Mode 3 | 1 | 1 | 高 | 上升沿 | 部分 EEPROM、SD 卡 |
三、片选控制与多从机连接
片选是 SPI 通信的“开关”。主机在发起传输前拉低目标从机的 CS,传输结束后拉高。CS 的时序要求包括:建立时间(CS 有效到第一个时钟边沿)、保持时间(最后一个时钟边沿到 CS 无效)以及 CS 拉高后的总线释放时间。若 CS 控制不当,会出现从机未选中、总线冲突或数据截断。
多从机连接主要有两种拓扑:
- 独立片选(Independent CS):所有从机共享 SCLK、MOSI、MISO,每个从机独占一根 CS。主机通过拉低对应 CS 选择目标。优点是软件简单、可任意访问;缺点是引脚占用随从机数量线性增长。
- 菊花链(Daisy Chain):从机串联,前一级 MISO 接下一级 MOSI,所有从机共享同一 CS。数据像移位寄存器一样逐级传递。优点是节省片选引脚;缺点是访问延迟随链长增加,且任一从机故障会影响整链,飞控中较少用于传感器,多用于多片 ADC 或 LED 驱动。
四、SPI 读写时序与驱动代码骨架
SPI 传输本质是“交换”:主机移出一位的同时从机移入一位。因此读操作通常需要先发送寄存器地址(或命令),再发送空字节以产生时钟,从而读回数据。以常见的“读寄存器”为例:
// 以 STM32 HAL 为例,读取 SPI 传感器寄存器
uint8_t spi_read_reg(uint8_t reg)
{
uint8_t tx[2] = { reg | 0x80, 0x00 }; // bit7=1 表示读
uint8_t rx[2] = { 0 };
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET); // 拉低片选
HAL_SPI_TransmitReceive(&hspi1, tx, rx, 2, 100); // 全双工交换
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET); // 拉高片选
return rx[1]; // 第二个字节为从机返回的数据
}
写寄存器时通常将地址最高位清零,并直接发送数据字节。注意:HAL 库的 HAL_SPI_TransmitReceive 会同时收发,因此接收缓冲区必须有效,否则读回数据丢失。
五、常见 SPI 传感器与场景
- ICM-42688-P / BMI088:高性能 6 轴 IMU,SPI 速率可达 24 MHz,Mode 0 或 Mode 3,飞控姿态解算核心。
- MS5611 / BMP388:气压计,SPI 读取压力与温度,用于高度估计。
- ICM-20948:9 轴 IMU,含磁力计,SPI 访问内部 DMP。
- W25Qxx:SPI NOR Flash,用于飞控日志存储,Mode 0/3。
- SD 卡:SPI 模式,用于黑匣子日志,Mode 0。
六、复盘与工程建议
在飞控工程中,SPI 驱动的稳定性往往决定姿态解算的可靠性。建议遵循以下实践:
- 初始化时先读取 WHO_AM_I 寄存器,确认器件在线与模式正确。
- 将 CS 引脚配置为推挽输出并默认拉高,避免上电误选中。
- 根据数据手册设置时钟分频,先低速验证,再逐步提高。
- 多从机时确保 MISO 共享总线上只有一个从机驱动,其余为高阻。
- 使用 DMA 或中断方式传输,避免阻塞主循环影响控制周期。
- 逻辑分析仪是排障首选工具,重点观察 CS 与第一个时钟边沿的关系。
掌握 SPI 的物理层、四种模式、片选拓扑与读写时序后,再结合具体传感器的寄存器手册,即可快速完成飞控传感器驱动的移植与调试。