2. SPI时序与模式:CPOL与CPHA详解
SPI(Serial Peripheral Interface)是一种同步、全双工、主从架构的串行通信协议。其核心在于主设备(Master)通过时钟信号(SCLK)控制数据采样与切换的时机。理解时钟极性(CPOL)和时钟相位(CPHA)是掌握SPI时序的关键,也是配置SPI设备驱动的基础。
2.1 CPOL与CPHA核心概念
CPOL(Clock Polarity)和CPHA(Clock Phase)共同决定了SPI总线的四种工作模式。这两个参数定义了时钟信号在空闲状态的电平以及数据采样/切换的边沿。
| 参数 | 含义 | 取值 | 说明 |
|---|---|---|---|
| CPOL | 时钟极性 | 0 | 空闲状态时SCLK为低电平(0) |
| 1 | 空闲状态时SCLK为高电平(1) | ||
| CPHA | 时钟相位 | 0 | 数据在SCLK的第一个边沿被采样(数据在第一个边沿之前准备好) |
| 1 | 数据在SCLK的第二个边沿被采样 |
关键记忆点: CPOL决定空闲电平,CPHA决定采样边沿是第一个还是第二个。两者组合形成Mode 0~3。
2.2 SPI Mode 0/1/2/3 定义与组合
根据CPOL和CPHA的不同组合,SPI定义了四种标准模式。每种模式都有其特定的时序波形特征。
| SPI Mode | CPOL | CPHA | 空闲时钟电平 | 数据采样边沿 | 数据切换边沿 |
|---|---|---|---|---|---|
| Mode 0 | 0 | 0 | 低电平 | 上升沿(第一个边沿) | 下降沿 |
| Mode 1 | 0 | 1 | 低电平 | 下降沿(第二个边沿) | 上升沿 |
| Mode 2 | 1 | 0 | 高电平 | 下降沿(第一个边沿) | 上升沿 |
| Mode 3 | 1 | 1 | 高电平 | 上升沿(第二个边沿) | 下降沿 |
常见设备兼容性: 大多数SPI外设(如Flash、传感器、ADC)默认支持Mode 0或Mode 3。Mode 0是最常用的模式,因为其采样边沿(上升沿)与大多数逻辑电路的默认行为一致。
2.3 四种模式的时序图(SVG)
以下SVG图展示了SPI Mode 0~3的典型时序波形,包含SCLK、MOSI(主出从入)和SS(从设备选择)信号。
2.4 时钟极性与相位配置
在嵌入式Linux驱动中,SPI模式的配置通常在设备树(Device Tree)或板级文件中完成。内核通过读取这些配置来初始化SPI控制器。
2.4.1 设备树中的配置示例
以下是在设备树中为SPI从设备指定模式的典型配置:
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi0>;
spidev@0 {
compatible = "spidev";
reg = <0>; /* 片选CS0 */
spi-max-frequency = <1000000>; /* 1MHz */
spi-cpol; /* CPOL = 1 */
spi-cpha; /* CPHA = 1 */
/* 上述两个属性组合为 Mode 3 */
};
};
配置说明: 如果设备树中同时设置了
spi-cpol 和 spi-cpha,则对应 Mode 3。如果只设置其中一个,则对应 Mode 1 或 Mode 2。如果两者都未设置,则默认为 Mode 0。
2.4.2 内核驱动中的配置方式
在SPI设备驱动中,可以通过 spi_setup() 函数或直接修改 spi_device 结构体成员来配置模式:
#include <linux/spi/spi.h>
static int my_spi_probe(struct spi_device *spi)
{
int ret;
/* 配置SPI模式为 Mode 0 */
spi->mode = SPI_MODE_0;
/* 或者使用位操作 */
/* spi->mode = SPI_CPOL | SPI_CPHA; // 对应 Mode 3 */
/* 设置最大频率 */
spi->max_speed_hz = 5000000; /* 5MHz */
/* 应用配置 */
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&spi->dev, "spi_setup failed\n");
return ret;
}
/* 后续通信 */
return 0;
}
2.5 典型波形分析
在实际调试中,使用逻辑分析仪或示波器抓取波形是验证SPI配置是否正确的最直接方法。以下是一个典型的SPI Mode 0波形分析案例。
常见调试陷阱:
- 模式不匹配: 主设备配置为Mode 0,但从设备要求Mode 3,会导致数据错位或通信失败。务必查阅从设备数据手册确认其支持的SPI模式。
- 时钟频率过高: 即使模式正确,如果SCLK频率超过从设备的最大支持频率,也会导致采样错误。
- 片选信号毛刺: 在模式切换或初始化阶段,片选信号可能出现毛刺,导致从设备误触发。建议在片选线上加10kΩ上拉电阻。
2.6 模式选择与驱动配置总结
下表总结了不同SPI模式在驱动开发中的典型应用场景和注意事项:
| SPI Mode | 典型应用 | 驱动配置宏 | 注意事项 |
|---|---|---|---|
| Mode 0 | 大多数SPI Flash、SD卡、传感器 | SPI_MODE_0 |
最常用,兼容性最好 |
| Mode 1 | 某些TI ADC、音频编解码器 | SPI_MODE_1 |
较少见,需确认设备手册 |
| Mode 2 | 某些Microchip外设、LCD控制器 | SPI_MODE_2 |
空闲高电平,注意电平转换 |
| Mode 3 | 多数SPI NOR Flash、W25Q系列 | SPI_MODE_3 |
与Mode 0一样常见,采样边沿不同 |
驱动开发最佳实践: 在编写SPI设备驱动时,不要硬编码模式。应该从设备树或平台数据中读取模式配置,或者提供模块参数让用户在加载时指定。这样可以提高驱动的可移植性和灵活性。