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