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:在第二个时钟边沿采样数据。
模式CPOLCPHA空闲电平采样边沿典型器件
Mode 000低上升沿多数 IMU、Flash
Mode 101低下降沿部分 ADC
Mode 210高下降沿少数传感器
Mode 311高上升沿部分 EEPROM、SD 卡
飞控驱动中,Mode 0 与 Mode 3 最常见。配置错误时典型现象是读回全 0、全 0xFF 或数据整体偏移一位,务必先核对数据手册中的 CPOL/CPHA 描述。

三、片选控制与多从机连接

片选是 SPI 通信的“开关”。主机在发起传输前拉低目标从机的 CS,传输结束后拉高。CS 的时序要求包括:建立时间(CS 有效到第一个时钟边沿)、保持时间(最后一个时钟边沿到 CS 无效)以及 CS 拉高后的总线释放时间。若 CS 控制不当,会出现从机未选中、总线冲突或数据截断。

多从机连接主要有两种拓扑:

  1. 独立片选(Independent CS):所有从机共享 SCLK、MOSI、MISO,每个从机独占一根 CS。主机通过拉低对应 CS 选择目标。优点是软件简单、可任意访问;缺点是引脚占用随从机数量线性增长。
  2. 菊花链(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。
常见误区:① 主从模式不一致导致读回全 0;② CS 未拉低或拉低后未等待建立时间;③ 多从机共享 MISO 时未将从机 MISO 配置为高阻,造成总线冲突;④ 时钟速率超过从机上限导致数据偶发错误;⑤ 菊花链中误以为可随机访问某一级。排障时应先用逻辑分析仪抓取 SCLK、MOSI、MISO、CS 四线波形,确认模式、片选与数据位序。
SPI 物理层与多从机拓扑 主设备 MCU SCLK / MOSI MISO / CS0..CSn 飞控主控 SPI1 / SPI2 SCLK MOSI MISO 从机 1 IMU CS0 从机 2 气压计 CS1 从机 3 Flash CS2 CS0 CS1 CS2 菊花链拓扑(共享 CS) 主设备 MOSI→ 从机 A → 从机 B 从机 B → MISO 回主 数据逐级移位,CS 同时选中整条链

六、复盘与工程建议

在飞控工程中,SPI 驱动的稳定性往往决定姿态解算的可靠性。建议遵循以下实践:

  1. 初始化时先读取 WHO_AM_I 寄存器,确认器件在线与模式正确。
  2. 将 CS 引脚配置为推挽输出并默认拉高,避免上电误选中。
  3. 根据数据手册设置时钟分频,先低速验证,再逐步提高。
  4. 多从机时确保 MISO 共享总线上只有一个从机驱动,其余为高阻。
  5. 使用 DMA 或中断方式传输,避免阻塞主循环影响控制周期。
  6. 逻辑分析仪是排障首选工具,重点观察 CS 与第一个时钟边沿的关系。

掌握 SPI 的物理层、四种模式、片选拓扑与读写时序后,再结合具体传感器的寄存器手册,即可快速完成飞控传感器驱动的移植与调试。