2. SPI 时序分析:采样、建立时间与时钟相位
SPI 调优,说白了就是跟时间赛跑。你想想看,数据在线上飞,主设备什么时候把数据推出去,从设备什么时候把它抓进来——这个时机要是没卡准,再高的频率也是白搭。
我刚开始做嵌入式那会儿,总觉得 SPI 时序就是调个极性相位完事。直到有一次,一块传感器死活读不出正确数据,示波器一挂才发现,采样沿刚好踩在数据跳变的边缘上。嗯,从那以后,我对时序就再也不敢马虎了。
2.1 采样沿与建立/保持时间
SPI 是同步串行协议,数据跟着时钟走。每个时钟周期,主设备在某个边沿把数据推上 MOSI/MISO 线,从设备在另一个边沿(或同一个边沿)把数据采样进来。
这里有两个关键时间参数:
- 建立时间(tSU):数据必须在采样沿到来之前稳定下来。这个窗口有多长?从数据线上电平稳定到采样时钟沿,中间的时间差。
- 保持时间(tH):采样沿之后,数据还得再维持一段时间,不能马上变。
说白了,建立时间和保持时间就是给数据留的「安全缓冲带」。如果时钟跑得太快,或者走线太长导致信号延迟,数据就可能在这个缓冲带里「晃悠」,采样结果自然就不靠谱了。
2.2 时钟极性与相位组合(CPOL & CPHA)
SPI 有四种工作模式,由两个参数决定:
- CPOL(Clock Polarity):空闲时时钟电平。CPOL=0 空闲低电平,CPOL=1 空闲高电平。
- CPHA(Clock Phase):数据采样发生在哪个边沿。CPHA=0 在第一个边沿采样,CPHA=1 在第二个边沿采样。
四种模式组合如下:
| 模式 | CPOL | CPHA | 采样沿 | 数据变化沿 |
|---|---|---|---|---|
| Mode 0 | 0 | 0 | 上升沿 | 下降沿 |
| Mode 1 | 0 | 1 | 下降沿 | 上升沿 |
| Mode 2 | 1 | 0 | 下降沿 | 上升沿 |
| Mode 3 | 1 | 1 | 上升沿 | 下降沿 |
Mode 0 和 Mode 3 是最常用的。为什么?因为它们的采样沿都是上升沿,而大多数 MCU 和传感器的内部逻辑都在上升沿采样,这样时序更干净。
2.3 多从机片选策略
一个 SPI 总线上挂多个从设备,最常见的方式就是每个从设备独占一条片选线(CS)。但这里有个坑:片选信号的切换时机。
我见过不少工程师在切换从设备时,直接拉高当前 CS,再拉低下一个 CS。这中间如果没留足够的时间间隔,总线上的数据可能会被「残留」的从设备误采样。
正确的做法是:
- 拉高当前 CS,结束当前传输。
- 等待至少一个时钟周期的「去抖时间」。
- 拉低目标 CS,开始新传输。
如果从设备数量多,还可以考虑菊花链拓扑。但菊花链的延迟会累加,不适合高频场景。
- 独立片选:每个从机一根 CS 线,控制简单,但占用 GPIO 多。
- 菊花链:一根 CS 线串联所有从机,节省引脚,但延迟大、调试复杂。
- GPIO 扩展片选:用译码器(如 3-8 译码器)扩展 CS 线,适合从机数量多且 GPIO 有限的场景。
2.4 时序分析实战:一个典型场景
假设你有一个 ADC 芯片,SPI 接口,最高支持 20MHz。你打算用 10MHz 跑。怎么确认时序没问题?
第一步,查数据手册,找到 ADC 的建立时间和保持时间要求。假设 tSU = 10ns,tH = 5ns。
第二步,计算你的系统能提供多少余量。10MHz 时钟周期是 100ns,半个周期是 50ns。如果数据变化沿在下降沿,采样沿在上升沿,那么数据从变化到采样有 50ns 的时间。
第三步,减去走线延迟、IO 驱动延迟等。假设总延迟 15ns,那么实际留给建立时间的是 50 - 15 = 35ns,远大于 10ns 的要求。OK,没问题。
但如果频率提到 20MHz,周期变成 50ns,半个周期 25ns,减去 15ns 延迟只剩 10ns,刚好卡在边界上。这时候就要小心了——温度变化、电压波动都可能吃掉这最后一点余量。
2.5 时序知识体系总览
下面这张图把 SPI 时序的核心知识点串起来了。你可以把它当作一个快速参考图谱:
这张图把 SPI 时序拆成了三个维度:采样时间、时钟相位、片选策略。你在实际调试时,可以对照这张图逐一排查——先看采样沿对不对,再看模式匹不匹配,最后检查片选切换有没有留足时间。三步走完,大部分时序问题都能定位。