Linux驱动开发SPI通信调试与常见问题汇总 - 第1节
1.1 SPI总线简介
SPI(Serial Peripheral Interface,串行外设接口)是由 Motorola 公司推出的一种高速、全双工、同步的串行通信总线。它广泛应用于嵌入式系统中连接微控制器与各种外设,如传感器、ADC/DAC、LCD 显示屏、SD 卡、Flash 存储器等。
核心特点:
- 同步通信:由主设备提供时钟信号,所有通信时序与时钟同步。
- 全双工:数据发送和接收可同时进行,互不干扰。
- 主从架构:一个主设备(Master)可控制一个或多个从设备(Slave)。
- 高速率:典型时钟频率从几 MHz 到几十 MHz,远高于 I²C 总线。
- 无地址机制:通过片选信号(CS)直接选中从设备,无需软件寻址。
SPI 总线在 Linux 内核中作为 SPI 子系统 实现,提供统一的框架来管理 SPI 控制器(Controller)和 SPI 设备(Device),驱动开发者只需按照标准接口编写设备驱动即可。
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 | 片选信号,低电平有效(通常),主设备通过拉低 CS 选中目标从设备。 |
💡 关键点:MOSI 和 MISO 是两条独立的数据线,这是 SPI 能够实现全双工通信的物理基础。与 I²C 的共享数据线不同,SPI 的发送和接收路径完全分离。
1.2.1 信号时序关系
SPI 通信的时序由 时钟极性(CPOL) 和 时钟相位(CPHA) 两个参数共同决定,它们定义了数据在时钟信号的哪个边沿被采样和移位。
| 模式 | CPOL | CPHA | 时钟空闲电平 | 数据采样边沿 |
|---|---|---|---|---|
| 模式 0 | 0 | 0 | 低电平 | 上升沿采样 |
| 模式 1 | 0 | 1 | 低电平 | 下降沿采样 |
| 模式 2 | 1 | 0 | 高电平 | 下降沿采样 |
| 模式 3 | 1 | 1 | 高电平 | 上升沿采样 |
⚠️ 常见问题:主设备和从设备的 SPI 模式必须匹配,否则会导致数据错位或通信失败。在 Linux 驱动中,通过
spi_device->mode 字段设置模式,例如 SPI_MODE_0。
1.3 全双工通信原理
SPI 的全双工特性是其区别于 I²C、UART 等半双工总线的最显著优势。全双工意味着在同一个时钟周期内,主设备可以通过 MOSI 发送数据,同时从设备可以通过 MISO 返回数据,两者互不干扰。
1.3.1 移位寄存器机制
SPI 通信的核心是 环形移位寄存器 结构。主设备和从设备内部各有一个相同位宽的移位寄存器(通常为 8 位或 16 位),通过 MOSI 和 MISO 连接成一个环形。
通信过程(以 8 位数据为例):
- 初始化:主设备将要发送的数据加载到其移位寄存器中,从设备也将要发送的数据加载到其移位寄存器中。
- 时钟驱动:主设备产生 8 个 SCLK 时钟脉冲。
- 逐位移位:每个时钟脉冲,主设备和从设备各自将移位寄存器中的最高位移出到数据线上,同时从数据线上移入一个比特位。
- 数据交换:经过 8 个时钟周期后,主设备发送的数据全部移入从设备的移位寄存器,从设备发送的数据全部移入主设备的移位寄存器。
- 完成:主设备从自己的移位寄存器中读取接收到的数据,即为从设备发送的数据。
1.3.2 全双工 vs 半双工对比
| 特性 | SPI(全双工) | I²C(半双工) | UART(全双工) |
|---|---|---|---|
| 数据线数量 | 2 条(MOSI + MISO) | 1 条(SDA) | 2 条(TX + RX) |
| 同时收发 | ✅ 支持 | ❌ 不支持 | ✅ 支持 |
| 时钟源 | 主设备提供 | 主设备提供 | 各自独立时钟 |
| 典型速率 | 10~80 MHz |