3. SPI 数据帧格式:8位/16位传输、MSB/LSB优先、数据采样与移位时序

SPI 协议的数据帧格式决定了主从设备之间如何组织、发送和接收每一位数据。理解帧格式是驱动开发中配置寄存器、解析数据包和调试通信异常的基础。本章将深入解析 SPI 数据帧的三大核心要素:帧长度(8位/16位)、位序(MSB/LSB优先)以及数据采样与移位的时序关系。

3.1 数据帧长度:8位与16位传输

SPI 协议本身并未强制规定数据帧的长度,但绝大多数硬件外设支持 8 位或 16 位两种基本模式。帧长度决定了每次片选(CS)有效期间,主设备通过 SCK 时钟发送和接收的数据位数。

帧长度 典型应用场景 驱动配置要点
8 位 传感器寄存器读写、ADC/DAC 配置、EEPROM 操作 数据寄存器为 8 位宽;发送/接收缓冲区按字节对齐
16 位 音频编解码器、高精度 ADC、LCD 显示驱动 数据寄存器为 16 位宽;注意字节序(大端/小端)
可变长度(4~32位) 高级 MCU 的 SPI 控制器(如 STM32、NXP LPC) 需配置帧格式寄存器(FRF/CR1.DFF);驱动需动态调整
驱动开发提示: 在配置帧长度时,务必检查从机设备数据手册中指定的帧格式。例如,某些传感器要求 16 位帧,但实际只使用高 12 位,低 4 位为填充位。驱动中应使用掩码操作提取有效数据,避免将填充位误判为有效信号。

3.2 MSB/LSB 优先:位序控制

位序(Bit Order)定义了数据帧中最高有效位(MSB)和最低有效位(LSB)的传输顺序。SPI 协议默认采用 MSB 优先,但许多外设支持通过寄存器位(如 LSBFE、LSBFIRST)切换为 LSB 优先。

  • MSB 优先(默认): 先发送数据的最高位(bit 7 或 bit 15),最后发送最低位(bit 0)。适用于大多数标准 SPI 设备。
  • LSB 优先: 先发送数据的最低位(bit 0),最后发送最高位(bit 7 或 bit 15)。常见于某些加密芯片、自定义协议或与旧设备兼容的场景。
常见陷阱: 主从设备的位序必须一致。如果主机配置为 MSB 优先,而从机配置为 LSB 优先,则接收到的数据会完全错位,导致通信失败。调试时,应首先使用示波器或逻辑分析仪检查 MOSI/MISO 线上的位顺序。

下图展示了 8 位数据帧在 MSB 优先和 LSB 优先下的传输顺序对比:

8位数据帧位序对比:MSB优先 vs LSB优先 MSB优先: b7 b6 b5 b4 b3 b2 b1 b0 传输方向(先发高位) LSB优先: b0 b1 b2 b3 b4 b5 b6 b7 传输方向(先发低位)

3.3 数据采样与移位时序

SPI 通信的核心在于主设备通过 SCK 时钟控制数据的移位输出和采样输入。数据采样与移位时序由 CPOL(时钟极性) 和 CPHA(时钟相位) 共同决定,但本节聚焦于数据在时钟边沿上的具体行为。

3.3.1 移位与采样的基本概念

  • 移位(Shift): 在每个 SCK 时钟边沿(上升沿或下降沿),发送方将数据寄存器中的一位数据移出到 MOSI(主机发送)或 MISO(从机发送)线上。
  • 采样(Sample): 在另一个 SCK 时钟边沿(与移位边沿相反),接收方对数据线上的电平进行采样,并将该位数据移入接收寄存器。

下图展示了在 CPOL=0、CPHA=0 模式下,8 位数据帧的移位与采样时序:

SPI 数据移位与采样时序(CPOL=0, CPHA=0) SCK ↑采样 ↓移位 ↑采样 ↓移位 ↑采样 ↓移位 ↑采样 ↓移位 MOSI b7 b6 b5 b4 b3 b2 b1 b0 数据在 SCK 下降沿移位 在 SCK 上升沿采样 MISO b7 b6 b5 b4 b3 b2 b1 b0 CS CS 低电平有效,数据帧传输期间保持低电平 帧起始 帧结束

3.4 驱动开发中的帧格式配置

在实际驱动开发中,帧格式的配置通常通过 SPI 控制器的寄存器完成。以下是一个基于 STM32 HAL 库的配置示例,展示如何设置 16 位帧、MSB 优先模式:

// SPI 句柄定义
SPI_HandleTypeDef hspi1;

// SPI 初始化函数
void MX_SPI1_Init(void)
{
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_16BIT;   // 16 位数据帧
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;  // CPOL = 0
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;      // CPHA = 0
    hspi1.Init.NSS = SPI_NSS_SOFT;              // 软件控制 CS
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;     // MSB 优先
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 10;
    
    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    {
        // 初始化错误处理
        Error_Handler();
    }
}
关键配置项:
  • DataSize:设置为 SPI_DATASIZE_16BIT 启用 16 位帧。
  • FirstBit:设置为 SPI_FIRSTBIT_MSB 启用 MSB 优先。
  • 如果从机要求 LSB 优先,则将 FirstBit 改为 SPI_FIRSTBIT_LSB。

3.5 数据采样与移位时序的驱动影响

采样与移位时序直接影响驱动中数据读取的时机和缓冲区管理策略。以下是两种常见场景的对比:

时序模式 移位边沿 采样边沿 驱动注意事项
CPHA=0 SCK 的第一个边沿(上升沿或下降沿,取决于 CPOL) SCK 的第二个边沿 数据在第一个边沿之前必须稳定;驱动需确保发送缓冲区在第一个时钟边沿前准备好
CPHA=1 SCK 的第二个边沿 SCK 的第一个边沿 数据在第一个边沿被采样;驱动需在第一个边沿之前完成数据移位
调试建议: 如果发现接收数据始终为 0x00 或 0xFF,或者数据整体左移/右移了一位,通常是因为采样边沿与移位边沿配置错误。使用逻辑分析仪观察 SCK 与 MOSI/MISO 的相对关系,确认数据是否在正确的时钟边沿被采样。

3.6 多从机扩展中的帧格式一致性

在多从机扩展场景中,所有从机设备必须使用相同的帧格式(帧长度、位序、采样时序),否则会导致通信混乱。驱动开发时,建议在系统初始化阶段统一配置所有从机的帧格式参数,并在运行时通过片选信号切换不同的从机。

下图展示了多从机系统中帧格式一致性的重要性:

多从机扩展中的帧格式一致性要求 SPI 主机 帧格式:8位/MSB/CPHA=0 从机 1 8位/MSB/CPHA=0 ✅ 匹配 从机 2 16位/LSB/CPHA=1 ❌ 不匹配 从机 3 8位/MSB/CPHA=0 ✅ 匹配 帧格式一致性规则 1. 所有从机的帧长度必须与主机一致 2. 所有从机的位序(MSB/LSB)必须与主机一致 3. 所有从机的 CPOL/CPHA 必须与主机一致 4. 如果从机 2 不匹配,需单独配置其寄存器 或使用独立的 SPI 总线 ⚠ 不匹配的从机会导致通信完全失败

3.7 本章小结

  • 帧长度: 8 位适用于大多数传感器和存储器,16 位适用于音频和高精度数据采集设备。驱动中需正确配置数据寄存器宽度。
  • 位序: MSB 优先是 SPI 默认标准,LSB 优先用于特殊场景。主从设备位序必须一致。
  • 采样与移位: 由 CPOL 和 CPHA 共同决定,驱动中需根据从机数据手册配置正确的时钟边沿。
  • 多从机扩展: 所有从机必须使用与主机一致的帧格式,否则需通过独立总线或寄存器配置解决。