1. SPI协议基础:从一根线到四根线的进化
大家好,我是你们的嵌入式驱动开发讲师。今天咱们聊聊SPI——这个在嵌入式世界里几乎无处不在的串行通信协议。
说实话,我刚入行那会儿,总觉得SPI不就是四根线嘛,有啥好学的?直到有一次调试一块LCD屏幕,死活刷不出图像,最后发现是时钟极性配反了……嗯,从那以后我再也不敢小看这四根线了。
1.1 SPI总线概述
SPI,全称Serial Peripheral Interface,串行外设接口。它由摩托罗拉公司在80年代推出,初衷很简单——给微控制器和外围设备之间搭一条高速通道。
你想想看,I2C虽然省引脚,但速度上不去;UART虽然简单,但只能点对点。SPI呢?速度可以跑到几十兆赫兹,还支持多设备,所以成了ADC、DAC、LCD、SD卡、传感器这些外设的标配接口。
SPI的核心特点:
- 全双工通信——发送和接收同时进行,不像I2C那样需要等应答
- 主从模式——一个主设备控制时钟,一个或多个从设备响应
- 同步通信——所有数据交换都由主设备产生的时钟驱动
- 高速率——典型速率在1MHz到50MHz之间,有些器件能跑到100MHz+
我个人习惯把SPI比作「乒乓对话」:主设备每发一个字节,从设备就回一个字节。你发出去的数据和收进来的数据,是同一时钟沿上完成的。这个特性在驱动开发中特别重要——后面讲中断和DMA的时候你会深有体会。
1.2 四线制信号定义
标准的SPI接口有四根信号线。我见过不少新手把这四根线搞混,尤其是MISO和MOSI——焊反了可是要飞线的。
| 信号名 | 全称 | 方向 | 作用 |
|---|---|---|---|
| SCLK | Serial Clock | 主→从 | 由主设备产生,同步数据传输 |
| MOSI | Master Out Slave In | 主→从 | 主设备发送数据给从设备 |
| MISO | Master In Slave Out | 从→主 | 从设备发送数据给主设备 |
| SS/CS | Slave Select / Chip Select | 主→从 | 片选信号,低电平有效,选中从设备 |
这里有个小细节:MOSI和MISO的名字是站在主设备角度定义的。所以从设备那边,MOSI引脚其实是数据输入,MISO是数据输出。我曾经见过一块国产芯片,它的数据手册把这两个引脚标反了,害得我排查了半天——所以拿到新芯片,第一件事就是核对引脚定义。
避坑指南: 多从机共用一个SPI总线时,所有从设备的SCLK、MOSI、MISO都并联在一起,但每个从设备必须有独立的SS引脚。我曾经为了省GPIO,用了一个译码器来选通SS,结果时序上出了点问题——后面讲多从机拓扑时会细说。
1.3 主从模式与多从机拓扑
SPI的通信模型很简单:一个主设备,一个或多个从设备。主设备负责产生时钟、控制片选、发起传输。从设备只能被动响应。
多从机拓扑有两种常见方式:
- 独立片选方式——每个从设备独占一根SS线,主设备用多个GPIO分别控制。优点是软件简单,缺点是占用引脚多。
- 菊花链方式——所有从设备共用SS和SCLK,但数据像串糖葫芦一样从一个设备传到下一个。优点是省引脚,缺点是延迟大、软件复杂。
我个人在实际项目中几乎只用独立片选方式。菊花链虽然看起来高级,但调试起来太痛苦了——任何一个从设备出问题,整条链都断了。
下面这张图展示了典型的单主多从拓扑结构:
1.4 时钟极性与相位(CPOL/CPHA)详解
好了,到了本章最核心、也最容易踩坑的部分——时钟极性和相位。我敢说,十个SPI驱动出问题,有八个是这里配错了。
CPOL(Clock Polarity) 决定时钟空闲时的电平:
- CPOL = 0:空闲时SCLK为低电平
- CPOL = 1:空闲时SCLK为高电平
CPHA(Clock Phase) 决定数据在哪个时钟沿被采样:
- CPHA = 0:在第一个时钟沿采样(上升沿或下降沿,取决于CPOL)
- CPHA = 1:在第二个时钟沿采样
组合起来就是四种模式:
| 模式 | CPOL | CPHA | 空闲电平 | 数据采样沿 | 数据变化沿 |
|---|---|---|---|---|---|
| 模式0 | 0 | 0 | 低 | 上升沿 | 下降沿 |
| 模式1 | 0 | 1 | 低 | 下降沿 | 上升沿 |
| 模式2 | 1 | 0 | 高 | 下降沿 | 上升沿 |
| 模式3 | 1 | 1 | 高 | 上升沿 | 下降沿 |
你可能会问:「这么多模式,我该用哪个?」
答案是:看从设备的数据手册。每个SPI从设备都会明确标注它支持哪种模式。比如常见的W25Q系列Flash,支持模式0和模式3;而某些ADC只支持模式1。
重要提醒: 主设备和从设备的CPOL和CPHA必须完全一致,否则数据会错位。我曾经调试一块OLED屏,图像一直花屏,用逻辑分析仪抓了波形才发现——主设备配的是模式0,从设备要的是模式3。就差一个时钟沿,折腾了我一整天。
下面这张时序图能帮你直观理解四种模式的区别:
这里分享一个我自己的记忆方法:「CPOL看空闲,CPHA看第几」。CPOL=0时空闲低电平,CPOL=1时空闲高电平;CPHA=0时第一个沿采样,CPHA=1时第二个沿采样。简单吧?
调试技巧: 如果你不确定从设备用哪种模式,可以用逻辑分析仪抓一下从设备在空闲时的SCLK电平——高就是CPOL=1,低就是CPOL=0。然后看数据变化发生在哪个沿,就能反推出CPHA。我每次拿到新模块,第一件事就是抓波形确认模式,绝不只看数据手册——因为手册也可能写错。
1.5 本章小结
好了,SPI协议的基础部分就讲到这里。我们聊了四根信号线的定义、主从拓扑的两种方式、以及最容易出错的时钟极性和相位配置。
记住一句话:SPI驱动开发,七分配置,三分代码。只要把CPOL/CPHA、时钟频率、数据位宽这些参数配对了,剩下的就是收发数据的事。配错了?嗯,那就准备好逻辑分析仪慢慢查吧。