3. SPI 硬件接口与信号协议:SCLK、MOSI、MISO、CS 信号详解、SPI 模式 (CPOL/CPHA) 配置、全双工与半双工通信

3.1 SPI 四线信号详解

SPI(Serial Peripheral Interface)是一种同步、全双工、主从架构的串行通信总线。在车载嵌入式系统中,SPI 常用于连接传感器(如加速度计、陀螺仪、压力传感器)、ADC/DAC 转换器、以及外部存储设备。其物理层由四条关键信号线构成:

信号名称 方向(主→从) 功能描述 车载典型连接
SCLK(串行时钟) 主 → 从 由主设备产生,决定数据传输速率和同步边沿 MCU SPI_CLK → 传感器 CLK
MOSI(主出从入) 主 → 从 主设备发送数据到从设备的数据线 MCU SPI_MOSI → 传感器 SDI
MISO(主入从出) 从 → 主 从设备发送数据到主设备的数据线 传感器 SDO → MCU SPI_MISO
CS(片选) 主 → 从 低电平有效,选中特定从设备开始通信 MCU GPIO → 传感器 CS
车载设计要点: 在高速 SPI(≥10 MHz)场景下,SCLK 和 MOSI 信号线应远离电源和时钟干扰源,建议在 PCB 上包地处理。CS 信号通常由普通 GPIO 控制,需注意上拉电阻配置,防止浮空误触发。

3.2 SPI 模式详解:CPOL 与 CPHA

SPI 协议通过时钟极性(CPOL)和时钟相位(CPHA)的组合定义四种工作模式。主从设备必须工作在相同模式下才能正确通信。

  • CPOL(Clock Polarity):定义 SCLK 空闲时的电平状态。
    • CPOL = 0:空闲时 SCLK 为低电平
    • CPOL = 1:空闲时 SCLK 为高电平
  • CPHA(Clock Phase):定义数据采样和切换的边沿。
    • CPHA = 0:在 SCLK 的第一个边沿(上升沿或下降沿)采样数据
    • CPHA = 1:在 SCLK 的第二个边沿采样数据
SPI 模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据输出边沿
模式 0 0 0 低 上升沿 下降沿
模式 1 0 1 低 下降沿 上升沿
模式 2 1 0 高 下降沿 上升沿
模式 3 1 1 高 上升沿 下降沿
常见传感器模式对照: 多数车载 MEMS 传感器(如 Bosch BMI088、ST LSM6DSO)默认使用 SPI 模式 0(CPOL=0, CPHA=0)。部分温度传感器(如 MAX31855)使用模式 1。务必查阅传感器数据手册确认。
SPI 四种模式时序对比(CPOL / CPHA) 模式0 (CPOL=0, CPHA=0) SCLK MOSI 采样 输出 模式1 (CPOL=0, CPHA=1) SCLK MOSI 采样 输出 模式2 (CPOL=1, CPHA=0) SCLK MOSI 采样 输出 模式3 (CPOL=1, CPHA=1) SCLK MOSI 采样 输出 时序解读要点: • 采样边沿:主设备在采样边沿读取 MISO 数据,从设备在采样边沿输出 MOSI 数据 • 输出边沿:数据在输出边沿切换,保证采样时数据已稳定 • 模式0和模式3最常用:模式0空闲低电平,模式3空闲高电平,两者采样边沿均为上升沿

3.3 全双工与半双工通信

SPI 标准协议天然支持全双工通信,即在同一时钟周期内,主设备通过 MOSI 发送数据,从设备通过 MISO 返回数据。但在车载传感器应用中,存在两种通信模式:

通信模式 数据流向 典型应用场景 优缺点
全双工 MOSI 和 MISO 同时传输 传感器寄存器读写、ADC 数据采集 吞吐量高,但需要 4 线连接
半双工 分时复用 MOSI/MISO 或单线双向 节省引脚、3 线 SPI 传感器 引脚少,但速率减半
车载半双工注意事项: 部分低成本传感器使用 3 线 SPI(无 MISO),通过半双工方式在 MOSI 线上分时收发。此时主设备需在发送完命令后立即将 MOSI 引脚切换为输入模式,并等待从设备驱动数据。Linux SPI 控制器驱动需配置 SPI_3WIRE 标志位。

3.4 Linux 内核 SPI 模式配置示例

在 Linux 内核中,SPI 模式通过 spi_device 结构体的 mode 字段配置。以下代码展示如何为车载传感器设置 SPI 模式 0 和全双工通信:

#include <linux/spi/spi.h>

static int sensor_spi_setup(struct spi_device *spi)
{
    // 设置 SPI 模式:CPOL=0, CPHA=0
    spi->mode = SPI_MODE_0;

    // 设置最大时钟频率(车载传感器通常 1-10 MHz)
    spi->max_speed_hz = 5 * 1000 * 1000; // 5 MHz

    // 设置每字位数(通常 8 位)
    spi->bits_per_word = 8;

    // 如果是 3 线半双工传感器,添加标志
    // spi->mode |= SPI_3WIRE;

    // 应用配置
    return spi_setup(spi);
}
调试技巧: 使用 spidev_test 工具验证模式配置:
# spidev_test -D /dev/spidev0.0 -s 5000000 -p "\xAA\xBB" -m 0
其中 -m 0 对应 SPI 模式 0,-s 设置时钟频率。

3.5 信号完整性对车载 SPI 的影响

在车载环境中,SPI 信号质量直接影响传感器数据可靠性。以下是常见问题及对策:

  • SCLK 振铃:时钟线过长或阻抗不匹配导致过冲/下冲,引起误采样。对策:串联 22-33 Ω 电阻,降低驱动强度。
  • CS 毛刺:GPIO 驱动不足或噪声耦合导致片选误触发。对策:CS 线加 10 kΩ 上拉电阻,软件去抖。
  • MISO 数据冲突:多从设备共用 MISO 线时,未选中设备未释放总线。对策:确保从设备具有三态输出,或使用 GPIO 隔离。
  • 时钟偏移:SCLK 与数据线长度差过大导致建立/保持时间不足。对策:等长布线,控制差分延迟 < 1 ns。
车载 SPI 信号完整性关键节点 主设备 (MCU) 从设备 (传感器) SCLK (时钟线) MOSI (数据线) MISO (数据线) CS (片选线) 信号完整性检查清单: 1. SCLK 频率是否在传感器规格范围内?(常见上限:5-10 MHz) 2. CS 片选时序是否满足建立时间(t_setup)和保持时间(t_hold)? 3. MISO 数据是否在采样边沿前稳定?(检查示波器眼图)

3.6 车载 SPI 传感器通信参数调优建议

基于以上信号协议分析,在车载 Linux 驱动开发中,建议按以下步骤进行参数调优:

  1. 确认传感器数据手册:获取 CPOL/CPHA、最大时钟频率、CS 时序要求。
  2. 设置 SPI 模式:在设备树或驱动中明确配置 spi-cpol 和 spi-cpha 属性。
  3. 调整时钟频率:从较低频率(如 1 MHz)开始,逐步提高至传感器支持的最大值,同时监测通信误码率。
  4. 优化 CS 控制:使用 GPIO 直接控制 CS,避免 SPI 控制器自动 CS 带来的延迟问题。
  5. 验证全双工时序:使用逻辑分析仪同时捕获 SCLK、MOSI、MISO 和 CS,确保数据对齐。
经验值参考: 在车载 12V 电源环境下,SPI 时钟频率建议不超过 10 MHz,且 SCLK 走线长度控制在 10 cm 以内。对于长距离传输(如跨 PCB 连接器),考虑使用 SPI 转差分信号芯片(如 MAX14840)。