SPI接口ADC采集系统联调与通信故障排查 - 第1节

一、SPI 四线制:SCLK、MOSI、MISO、CS 到底在干什么?

SPI,全称 Serial Peripheral Interface,串行外设接口。说白了,就是让主设备(比如 FPGA 或 MCU)和从设备(比如 ADC 芯片)之间快速交换数据的一种方式。

我刚开始接触 SPI 时,总觉得它名字挺唬人。后来发现,它其实就是四根线的事。你想想看,两根数据线、一根时钟线、一根片选线,搞定。

1.1 四根线的角色分工

信号线 全称 方向 一句话职责
SCLK Serial Clock 主 → 从 由主机产生,决定数据传输的节奏
MOSI Master Out Slave In 主 → 从 主机发送数据给从机
MISO Master In Slave Out 从 → 主 从机发送数据给主机
CS Chip Select 主 → 从 片选信号,低电平有效,选中哪个从机就跟谁通信

这里有个关键点:SCLK 永远由主机产生。从机只是被动地跟着时钟走。我见过不少新手把时钟方向搞反,结果数据死活读不出来。

核心记忆点:SPI 是同步通信,所有数据移位都发生在 SCLK 的边沿上。没有时钟,就没有数据传输。

1.2 为什么叫“四线制”?

其实严格来说,SPI 还有三线制(比如只用一个双向数据线),但咱们做 ADC 采集,99% 的场景都是四线制。四根线各司其职,全双工通信——也就是说,主机发数据的同时,从机也能往回发数据。

我调试过一个项目,ADC 芯片明明支持四线 SPI,结果 PCB 走线时把 MOSI 和 MISO 接反了。嗯,那画面太美,读回来的数据全是乱码。后来我养成了一个习惯:上电前先用万用表量一下这两根线有没有接反。

二、极性与相位:CPOL 和 CPHA 到底怎么配?

很多工程师觉得 SPI 协议难,其实难点就卡在 CPOL 和 CPHA 这两个参数上。我当年也被它们绕晕过。

简单来说:

  • CPOL(Clock Polarity):决定时钟空闲时是高电平还是低电平。
  • CPHA(Clock Phase):决定数据是在时钟的上升沿采样,还是下降沿采样。

2.1 四种模式一览

模式 CPOL CPHA 空闲时钟电平 数据采样边沿 数据输出边沿
模式 0 0 0 低电平 上升沿 下降沿
模式 1 0 1 低电平 下降沿 上升沿
模式 2 1 0 高电平 下降沿 上升沿
模式 3 1 1 高电平 上升沿 下降沿

你可能会问:这么多模式,到底用哪个?

答案是:看从机的手册。ADC 芯片会明确告诉你它支持哪种模式。我见过最坑的一次,芯片手册写的是“模式 0”,结果实际测试发现它工作在模式 3。后来发现是手册勘误。所以,我建议你拿到芯片后,先用示波器抓一下波形,确认一下实际行为。

避坑指南:我曾经在一个量产项目中,因为 SPI 模式配置错误,导致 10% 的板子在高温下通信失败。后来排查发现,CPHA 配置跟芯片内部时序差了半个时钟周期。从那以后,我每次选型都会仔细核对 SPI 模式的时序图,绝不只看文字描述。

三、SPI 时序图:一图胜千言

光说理论不够,咱们直接看时序图。下面这张 SVG 图展示了模式 0 和模式 3 的典型波形。

SPI 模式 0 与模式 3 时序对比 模式 0 (CPOL=0, CPHA=0) 空闲低电平,上升沿采样 ↑ 采样 MOSI Bit 7 Bit 6 Bit 5 Bit 4 模式 3 (CPOL=1, CPHA=1) 空闲高电平,上升沿采样 ↑ 采样 CS CS 低电平有效,整个传输期间保持低电平 注意:模式 0 和模式 3 的采样边沿都是上升沿,但空闲电平不同,导致数据有效窗口有差异

从图上你能看到:模式 0 和模式 3 的采样边沿都是上升沿,但空闲电平不同。这意味着什么?意味着如果你把模式 0 的代码直接套到模式 3 的芯片上,数据可能会错位一个时钟周期。

我的调试习惯:每次拿到新 ADC 芯片,我会先写一个简单的回环测试——让主机发一串已知数据,然后读回从机的响应。如果读回来的数据跟预期一致,说明 SPI 模式配置对了。如果不对,先别急着改代码,用示波器抓一下 SCLK 和 MOSI 的波形,看看边沿对齐情况。

四、SPI 通信流程:一个完整的数据交换周期

一个完整的 SPI 传输过程,其实就三步:

  1. 拉低 CS:主机把 CS 信号从高电平拉到低电平,通知从机“我要跟你说话了”。
  2. 时钟驱动数据:主机在 SCLK 上产生时钟脉冲,同时在 MOSI 上逐位发送数据;从机在 MISO 上逐位返回数据。
  3. 拉高 CS:主机把 CS 拉回高电平,表示本次传输结束。

这里有个细节:SPI 是全双工的。也就是说,主机发一个字节的同时,从机也在发一个字节。很多新手以为 SPI 是“一问一答”式的半双工,其实不是。你发 8 个时钟,就能同时收到 8 位数据。

我调试过一个 16 位 ADC,它的转换结果需要 16 个时钟才能读完。当时我犯了个低级错误:只发了 8 个时钟就拉高了 CS,结果读回来的数据只有高 8 位,低 8 位全是 0。嗯,从那以后我每次都会数一下时钟个数。

五、SPI 与 ADC 采集的第一次握手

ADC 芯片通过 SPI 接口输出数字量。常见的流程是:

  • 主机拉低 CS,通知 ADC 开始转换。
  • ADC 在 SCLK 的驱动下,逐位输出转换结果。
  • 主机在 MISO 上读取数据,同时可以通过 MOSI 发送配置命令(比如切换通道、设置增益)。

我个人习惯在 FPGA 里用一个状态机来控制这个流程:空闲态 → 启动转换态 → 等待转换完成态 → 读取数据态 → 回到空闲态。这样逻辑清晰,也方便调试。

关键参数速查:

  • SCLK 频率:通常 1MHz ~ 20MHz,具体看 ADC 手册
  • CS 建立时间:拉低 CS 后,至少等几个纳秒再开始发时钟
  • CS 保持时间:最后一个时钟结束后,至少等几个纳秒再拉高 CS

这些时序参数,手册里都会给。我建议你把这些参数做成一个表格,贴在工位上。调试时一眼就能看到,不用每次都翻手册。

六、本章小结

SPI 四线制其实不复杂。记住四根线的分工,搞懂 CPOL 和 CPHA 的四种组合,再配合示波器确认波形,基本就能搞定 90% 的 SPI 通信问题。