1. SPI协议基础:从波形到实战

SPI,全称Serial Peripheral Interface,串行外设接口。说白了,就是让主控芯片和外围设备之间快速交换数据的一种总线协议。我最早接触SPI是在做一款温湿度传感器驱动的时候,当时觉得这东西比I2C简单多了——线少、速度快、逻辑直白。但后来在调试LCD屏幕时才发现,越是简单的东西,坑往往越隐蔽。

咱们先从最基础的说起。

1.1 四线制:SPI的物理层

标准的SPI接口有四根信号线,少一根都不行(除非你只用单向传输)。这四根线各司其职,我习惯把它们分成两类:控制线和数据线。

信号线 全称 方向 作用
SCLK Serial Clock 主→从 时钟信号,由主机产生,决定传输速率
MOSI Master Out Slave In 主→从 主机发送数据给从机
MISO Master In Slave Out 从→主 从机发送数据给主机
CS Chip Select 主→从 片选信号,低电平有效,选中目标设备

这里有个细节:CS片选信号。我见过不少新手直接把CS接地,觉得反正只接一个设备。嗯,这在某些场景下确实能工作,但一旦你接了两个SPI设备,总线就打架了。我曾经在一个项目里吃过这个亏——两个传感器共用SPI总线,CS没独立控制,结果数据全乱套。

我的习惯:即使只接一个设备,也把CS接到GPIO上由软件控制。这样后期扩展时不用改硬件,改几行代码就行。

1.2 时序分析:数据是怎么传的?

SPI的传输过程其实很直观。你想想看:主机拉低CS,告诉从机“我要跟你说话了”。然后SCLK开始跳变,每个时钟周期,主机通过MOSI送出一位数据,同时从机通过MISO送回一位数据。所以SPI是全双工的——收发同时进行。

为什么会这样?因为SPI本质上是一个环形移位寄存器。主机和从机内部各有一个8位的移位寄存器,时钟每跳一次,两个寄存器就交换一位数据。8个时钟周期后,数据就交换完了。

核心要点:SPI每发送一个字节,同时也会接收一个字节。如果你只关心发送,接收到的数据可以忽略;但如果你需要读取从机的数据,就必须主动发送一个字节来“撬动”时钟。

我调试LCD驱动时,经常用逻辑分析仪抓波形。有一次发现屏幕花屏,抓了波形才发现——主机发送完数据后,CS拉高的时机早了半个时钟周期,导致从机没收到最后一位。这种问题,光看代码是看不出来的。

1.3 CPOL/CPHA模式详解

这是SPI协议里最容易让人迷糊的地方。CPOL和CPHA各占1位,组合起来就是4种模式。很多LCD数据手册里会明确写“SPI Mode 0”或“SPI Mode 3”,其实就是指这个。

先看定义:

  • CPOL(Clock Polarity):时钟极性。决定SCLK空闲时的电平。
    • CPOL=0:空闲时SCLK为低电平
    • CPOL=1:空闲时SCLK为高电平
  • CPHA(Clock Phase):时钟相位。决定数据在哪个边沿采样。
    • CPHA=0:在第一个边沿采样(上升沿或下降沿,取决于CPOL)
    • CPHA=1:在第二个边沿采样

组合起来就是4种模式:

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

怎么记?我有个笨办法:Mode 0和Mode 3是最常用的。Mode 0是CPOL=0、CPHA=0,空闲低电平,上升沿采样;Mode 3是CPOL=1、CPHA=1,空闲高电平,上升沿采样。你看,虽然空闲电平不同,但采样边沿都是上升沿。很多LCD控制器默认就支持这两种模式。

避坑指南:我曾经在一个项目里,MCU的SPI外设配置成Mode 0,但LCD数据手册写的是“SPI Mode 3”。我心想就差一个CPOL,应该能工作吧?结果屏幕死活不亮。后来用示波器一看,时钟空闲电平不对,从机根本不认。所以一定要严格匹配数据手册指定的模式,别想当然。

1.4 知识体系总览

下面这张图把SPI协议基础的核心知识点串起来了。你可以把它当作本章的“地图”,后面调试时随时回来对照。

SPI协议基础知识体系 SPI总线协议 四线制物理层 数据传输时序 CPOL/CPHA模式 SCLK MOSI MISO CS 全双工传输 移位寄存器 CS时序 字节传输 CPOL CPHA Mode 0 Mode 3 调试要点 逻辑分析仪抓波形 → 确认CS时序 → 核对CPOL/CPHA → 检查数据边沿

1.5 实战中的模式选择建议

做LCD驱动时,我建议你优先尝试Mode 0。为什么?因为大部分MCU的SPI外设默认配置就是Mode 0,而且很多LCD控制器(比如常见的ILI9341、ST7789)都支持Mode 0和Mode 3。如果Mode 0不行,再试Mode 3。

但要注意:不要同时修改CPOL和CPHA。我见过有人调试时,Mode 0不行,就直接跳到Mode 3,结果还是不行。正确的做法是:先确认数据手册,然后一次只改一个参数,用逻辑分析仪看波形变化。

我的调试流程:

  1. 读数据手册,找到SPI模式说明(通常在“Serial Interface”章节)
  2. 配置MCU的SPI外设,匹配模式
  3. 用逻辑分析仪抓取CS、SCLK、MOSI波形
  4. 对照数据手册的时序图,确认边沿对齐
  5. 如果花屏或没反应,先怀疑模式配置,再怀疑时钟频率

嗯,SPI协议基础就讲到这里。这些内容看起来简单,但后面调试LCD驱动时,你会发现——90%的通信问题都出在模式不匹配和时序违规上。把基础打牢,后面才能快速定位故障。