1. SPI协议基础
1.1 SPI总线物理层概述
SPI(Serial Peripheral Interface,串行外设接口)是由Motorola公司推出的一种高速、全双工、同步的串行通信总线。在嵌入式Linux系统中,SPI广泛应用于传感器、ADC/DAC、LCD控制器、Flash存储器、无线收发模块等外设的通信。
SPI总线在物理层采用主从架构(Master-Slave),通常包含1个主设备(Master)和1个或多个从设备(Slave)。主设备负责产生时钟信号并控制片选信号,从设备被动响应。
关键特性:
- 全双工通信:数据发送和接收同时进行
- 同步传输:由主设备提供的时钟信号同步
- 高速率:典型速率可达数十MHz,远高于I²C
- 无地址机制:通过片选信号(CS)选择从设备
- 无应答机制:硬件层不提供数据确认
1.2 四线制信号定义
标准SPI总线使用4根信号线,每根线的功能定义如下表所示:
| 信号线 | 全称 | 方向 | 功能描述 |
|---|---|---|---|
| SCLK | Serial Clock | Master → Slave | 由主设备产生的串行时钟信号,决定数据传输速率 |
| MOSI | Master Out Slave In | Master → Slave | 主设备输出数据线,从设备在该线上接收数据 |
| MISO | Master In Slave Out | Slave → Master | 从设备输出数据线,主设备在该线上接收数据 |
| CS | Chip Select | Master → Slave | 片选信号,低电平有效,用于选中目标从设备 |
调试提示:在驱动调试初期,使用逻辑分析仪或示波器同时抓取SCLK、MOSI、MISO、CS四根信号线,是判断SPI通信是否正常的最直接手段。常见问题包括:CS信号毛刺、SCLK极性错误、MOSI/MISO电平不匹配。
1.3 四线制时序分析
SPI总线的一次完整数据传输过程如下:
- 片选阶段:主设备将目标从设备的CS引脚拉低,选中该从设备。
- 时钟启动:主设备开始产生SCLK时钟信号。
- 数据移位:在每个时钟周期,主设备通过MOSI发送1位数据,同时从设备通过MISO发送1位数据,实现全双工传输。
- 传输结束:主设备停止SCLK时钟,并将CS引脚拉高,释放从设备。
下图展示了SPI总线在模式0(CPOL=0, CPHA=0)下的典型时序波形:
1.4 时钟极性(CPOL)与相位(CPHA)详解
SPI协议定义了4种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)两个参数组合决定。这两个参数决定了SCLK在空闲状态的电平以及数据采样/移位的边沿。
1.4.1 参数定义
| 参数 | 取值 | 含义 |
|---|---|---|
| CPOL (时钟极性) |
0 | SCLK空闲时为低电平(低电平有效) |
| 1 | SCLK空闲时为高电平(高电平有效) | |
| CPHA (时钟相位) |
0 | 数据在SCLK的第一个边沿(上升沿或下降沿)被采样 |
| 1 | 数据在SCLK的第二个边沿被采样 |
1.4.2 四种模式对比
| 模式 | CPOL | CPHA | 空闲时钟电平 | 数据采样边沿 | 数据移位边沿 | 典型应用 |
|---|---|---|---|---|---|---|
| 模式0 | 0 | 0 | 低电平 | 上升沿 | 下降沿 | 大多数SPI Flash、SD卡 |
| 模式1 | 0 | 1 | 低电平 | 下降沿 | 上升沿 | 部分ADC、DAC |
| 模式2 | 1 | 0 | 高电平 | 下降沿 | 上升沿 | 某些传感器 |
| 模式3 | 1 | 1 | 高电平 | 上升沿 | 下降沿 | 部分无线收发模块 |
驱动调试常见陷阱:主设备和从设备的SPI模式必须完全一致,否则会导致数据错位或通信失败。在Linux内核中,SPI设备树节点通过
spi-cpol 和 spi-cpha 属性配置模式。调试时务必核对从设备数据手册中指定的模式。
1.5 四种模式的时序对比SVG
1.6 多从设备连接拓扑
SPI总线支持多从设备连接,主要有两种拓扑结构:
| 拓扑类型 | 连接方式 | 优点 | 缺点 |
|---|---|---|---|
| 独立片选 | 每个从设备独占一根CS线,SCLK/MOSI/MISO共享 | 各从设备独立工作,互不干扰 | 占用主设备GPIO资源较多 |
| 菊花链 | 从设备串联,数据逐级传递 | 节省CS线,适合大量同类型设备 | 延迟累积,驱动实现复杂 |
Linux内核中的SPI设备树配置示例:
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
cs-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>,
<&gpio1 1 GPIO_ACTIVE_LOW>;
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>; /* CS0 */
spi-max-frequency = <50000000>;
spi-cpol; /* CPOL=1 */
spi-cpha; /* CPHA=1 */
};
sensor@1 {
compatible = "vendor,spi-sensor";
reg = <1>; /* CS1 */
spi-max-frequency = <10000000>;
/* 默认模式0,不设置spi-cpol/spi-cpha */
};
};
1.7 SPI与I²C总线对比
在嵌入式系统中,SPI和I²C是最常用的两种串行总线。下表从多个维度进行对比:
| 对比维度 | SPI | I²C |
|---|---|---|
| 信号线数量 | 4线(SCLK/MOSI/MISO/CS) | 2线(SCL/SDA) |
| 通信方式 | 全双工 | 半双工 |
| 传输速率 | 典型10~80MHz,最高可达100MHz+ | 标准100kHz,快速400kHz,高速3.4MHz |
| 从设备选择 | 硬件片选(CS) | 软件寻址(7位/10位地址) |
| 硬件复杂度 | 较高(需要更多引脚) | 较低(引脚少,支持多主) |
| 数据确认 | 无硬件ACK | 有硬件ACK/NACK |
| 典型应用 | Flash、ADC、LCD、无线模块 | 传感器、EEPROM、RTC |