3、SPI 工作模式:模式 0/1/2/3 详解、全双工通信机制、主从设备配置
SPI(Serial Peripheral Interface)总线在网关嵌入式系统中承担着高速、全双工的片间通信任务。理解其四种工作模式(CPOL/CPHA 组合)、全双工数据流以及主从拓扑结构,是编写正确 SPI 设备驱动的核心前提。本节将从时序参数、模式对比、数据交换机制和配置要点四个维度展开。
3.1 SPI 模式 0/1/2/3 的时序本质
SPI 模式由时钟极性(CPOL)和时钟相位(CPHA)两个参数唯一确定。CPOL 决定空闲时 SCK 的电平,CPHA 决定数据采样发生在 SCK 的第一个还是第二个边沿。
| 模式 | CPOL | CPHA | 空闲 SCK 电平 | 数据采样边沿 | 数据输出边沿 |
|---|---|---|---|---|---|
| 模式 0 | 0 | 0 | 低电平 | 上升沿(第一个边沿) | 下降沿 |
| 模式 1 | 0 | 1 | 低电平 | 下降沿(第二个边沿) | 上升沿 |
| 模式 2 | 1 | 0 | 高电平 | 下降沿(第一个边沿) | 上升沿 |
| 模式 3 | 1 | 1 | 高电平 | 上升沿(第二个边沿) | 下降沿 |
驱动适配提示: 绝大多数 SPI 从设备(如 Flash、ADC、传感器)默认使用模式 0 或模式 3。在 Linux 内核中,通过
spi_device->mode 字段设置 SPI_MODE_0 至 SPI_MODE_3 宏。务必核对从设备数据手册中的时序图,错误的模式会导致数据移位或 CRC 错误。
3.2 全双工通信机制
SPI 的全双工特性源于其独立的发送和接收数据路径:主设备通过 MOSI 线发送数据,同时通过 MISO 线接收从设备数据。一个时钟周期内,主从双方各移出一位数据并移入对方的一位数据,形成“交换式”传输。
核心机制: SPI 没有独立的应答信号,主设备必须主动发起时钟才能读取从设备数据。因此,读操作通常需要先发送一个“空字节”(0x00 或 0xFF)来产生时钟,从设备在相同字节时间内返回数据。
3.3 主从设备配置与片选管理
SPI 总线采用一主多从的拓扑结构。主设备通过独立的片选信号(CS/SS)选择目标从设备,每次只与一个从设备通信。在 Linux 内核中,主从配置通过 struct spi_device 和 struct spi_board_info 完成。
3.3.1 硬件连接要点
- SCK:主设备输出,所有从设备共享。
- MOSI:主设备输出,所有从设备数据输入引脚共享。
- MISO:从设备输出,所有从设备数据输出引脚共享(从设备未选中时需输出高阻态)。
- CS:每个从设备独立占用一个主设备 GPIO 或专用片选线,低电平有效。
3.3.2 内核配置示例
/* 板级文件或设备树中的 SPI 从设备声明 */
static struct spi_board_info my_spi_devices[] = {
{
.modalias = "mcp2515", /* 驱动名称 */
.max_speed_hz = 10 * 1000 * 1000, /* 10 MHz */
.bus_num = 1, /* SPI 控制器编号 */
.chip_select = 0, /* 片选索引 */
.mode = SPI_MODE_0, /* 工作模式 */
.platform_data = &mcp2515_pdata,
},
};
避坑指南: 多个从设备共享 MISO 线时,必须确保未选中的从设备 MISO 引脚为高阻态(三态),否则会造成总线冲突。部分从设备不支持三态输出,此时需要为每个从设备增加一个三态缓冲器或使用独立的 SPI 控制器。
3.4 驱动开发中的模式与配置校验
在 Linux SPI 子系统驱动中,模式配置和全双工通信通过 spi_transfer 结构体实现。以下是一个典型的读写操作片段:
struct spi_transfer t = {
.tx_buf = tx_buffer, /* 发送数据缓冲区 */
.rx_buf = rx_buffer, /* 接收数据缓冲区(全双工) */
.len = 4, /* 传输字节数 */
.speed_hz = 5000000, /* 5 MHz 传输速率 */
.bits_per_word = 8, /* 8 位数据宽度 */
.cs_change = 0, /* 传输完成后是否释放片选 */
};
struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);
spi_sync(spi_device, &m); /* 同步阻塞传输 */
模式校验清单:
- 确认从设备数据手册中 CPOL 和 CPHA 的时序图,而非仅看模式编号。
- 检查 SPI 控制器硬件是否支持所需模式(部分控制器只支持模式 0 和模式 3)。
- 验证片选极性:大多数从设备使用低电平有效,但部分设备要求高电平有效。
- 测试全双工回环:将 MOSI 与 MISO 短接,发送已知数据并验证接收是否一致。
3.5 常见问题与调试方法
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 数据全部为 0xFF 或 0x00 | 片选未正确拉低 / MISO 未连接 | 用示波器检查 CS 和 MISO 电平 |
| 数据移位(如 0x55 变成 0xAA) | CPOL/CPHA 配置错误 | 核对时序图,调整模式参数 |
| 偶尔通信失败 | 时钟频率过高 / 信号反射 | 降低 max_speed_hz,增加串联电阻 |
| 多从设备数据冲突 | 未选中设备 MISO 未高阻 | 检查从设备三态特性或增加缓冲器 |