SPI 总线:快,但要多几根线
接一块 1.8 寸彩屏,或者插一张 SD 卡,会发现线突然变多了——不像 I2C 那两根,动辄要接六七根。这是因为它们走的是 SPI。SPI 拿引脚换速度:线是多了,但跑得飞快,几十 MHz 是常事,一屏画面几毫秒就刷完。要传图像、要读大文件,几乎只能靠它。
SPI 到底是个什么总线
一句话:一个主控带一群从设备的、四根线的、全双工的高速同步总线。拆开看几个关键词——
同步,指它跟 I2C 一样自带一根时钟线,收发双方踩着同一个节拍走,不像串口 UART 那样两头各定各的波特率、对不上就乱码。全双工,指发和收各走各的线、能同时进行,这是它比 I2C 快的一半原因。高速,指时钟能拉到几十 MHz,远超 I2C 那几百 kHz 到几 MHz 的水平。
四根线各干什么
SPI 靠四根线干活,名字有点绕,可以这么记:
- SCLK(时钟):主控打的节拍,跟 I2C 的 SCL 一个作用,大家踩着这个点收发。SCLK 从不空转——主控想通信才发时钟,不想通信就停着。
- MOSI(主出从入,Master Out Slave In):主控往从设备发的数据走这根。
- MISO(主入从出,Master In Slave Out):从设备回给主控的数据走这根。
- CS(片选,Chip Select):主控对某个从设备喊"该你了",把它的 CS 拉低,这个设备才上线开口。
MOSI 和 MISO 是两根独立的线,一根专管发、一根专管收,所以收发能同时进行(全双工)。这跟 I2C 只有一根 SDA 双向轮流用(半双工)不一样,也是 SPI 快的底气之一。
CS 有个容易忽略的细节:它是低电平有效(CS 低才选中)。而且 CS 通常就是主控随便挑一个普通 GPIO 来拉高拉低,不占用什么专门外设——想接几个从设备,就再匀出几个 GPIO 当 CS 就行。普通 IO 怎么控高低看 /principle/gpio/。
时钟极性与相位:接不上多半在这
SPI 有个新手最容易栽的坑:模式。同样是"踩着时钟收发",可到底踩时钟的哪个边沿、时钟没活时停在高还是低,这里有讲究,配不齐就读不到数据。
它由两个参数决定:
- CPOL(时钟极性):SCLK 空闲(没在通信)时停在高电平还是低电平。CPOL=0 空闲拉低,CPOL=1 空闲拉高。
- CPHA(时钟相位):数据在时钟的第一个沿采样,还是第二个沿采样。CPHA=0 取第一个沿,CPHA=1 取第二个沿。
两个参数各有 0/1 两种取值,两两组合出 mode 0(0,0)、mode 1(0,1)、mode 2(1,0)、mode 3(1,1) 四种模式。主控和从设备必须用同一个 mode,采样的边沿才对得齐——一头在上升沿放数据、另一头也得在上升沿去读,错开一个沿,读到的全是垃圾。为什么屏幕库常给个"试着换 mode 0 到 3 挨个试"的建议?就是因为个别模块 datasheet 没写清、或写反了,四个模式一共就四种,挨个试比查手册还快。
所以线全接对了、电源也正常,屏幕却一片黑或者花屏,先怀疑模式设错了,别急着拆线。
SPI 接不上,第一件事不是查线,是查两头的 SPI 模式(mode 0~3)和 CS 引脚号对不对。模块的 datasheet 或商品页一般会写它用 mode 几——绝大多数器件是 mode 0。
多个从设备:一个从设备一根 CS
想在一组 SPI 上挂多个设备(比如同时接彩屏和 SD 卡)?SCLK、MOSI、MISO 这三根线可以共用,接到同一组信号上;但每多一个从设备,就要多拉一根 CS 单独点名。
主控想跟谁说话,就只把谁的 CS 拉低,其它设备的 CS 全拉高——被拉高的设备就"装睡",MISO 上不吭声,不去抢总线。这样同一组线上就能轮流跟不同设备通信。
这跟 I2C 用地址点名是两种思路:I2C 靠"门牌号"(设备地址)区分,两根线就能挂一串;SPI 靠"一人一根片选线",设备越多、占的 GPIO 越多。省线还是省速度,权衡就在这。I2C 那套地址寻址看 /principle/i2c/。
SPI vs I2C 怎么选
| SPI | I2C | |
|---|---|---|
| 速度 | 快(几十 MHz) | 慢(一般几 MHz 内) |
| 占线 | 4 根起,每多一从加 1 根 CS | 固定 2 根 |
| 寻址 | 靠 CS 片选(一从一线) | 靠设备地址(门牌号) |
| 双工 | 全双工(收发同时) | 半双工(收发轮流) |
一句话:SPI 快但费线,I2C 省线但慢。三种常见串行总线放一起横向对比、什么场景选哪个,看 /principle/protocol-compare/;串口那条线看 /principle/uart/。
什么时候用它
判断很简单:要快、要传大量数据的,走 SPI。典型器件都是这类——
- TFT 彩屏:一屏几万个像素,几十 MHz 才刷得动,I2C 那点速度带不起来。
- SD 卡:读写文件动辄几十 KB 起步,得靠 SPI 的高带宽。
- SPI Flash:外挂存储、大字库、固件,都走 SPI 读。
- 高速 ADC、RC522 读卡模块(见 /sensor/rc522/)。
反过来,要省引脚、设备又多又不赶时间的,比如一堆小传感器加块小 OLED(见 /guide/l2-oled/),用 I2C 更合适。
补两个 ESP32 实战点。其一,ESP32 有 VSPI 和 HSPI 两组 SPI 外设,接两个 SPI 设备(比如一块屏加一张 SD 卡)时可以分到两组上,互不抢总线、各跑各的。其二,SPI 速度不是越高越好——线一长、飞线一多,几十 MHz 的时钟就容易受干扰出错,屏花、SD 读写失败往往是时钟拉太高了。接不上、不稳时,先把时钟降到几 MHz 让它先跑通,稳定了再往上加,比一上来顶格调更省事。
SPI 还能更快:Dual/Quad 和 DMA
标准 SPI 一个时钟沿只在 MOSI 上传 1 位,想更快只能死拉时钟。但外挂 Flash、部分大彩屏还有另一条路:多拉几根数据线并行传。
- Dual SPI:把平时收数据的 MISO 也临时改成发数据用,一个时钟同时走 2 位,读 Flash 快近一倍。
- Quad SPI(QSPI):再借两根 IO 凑齐 4 根数据线,一个时钟传 4 位。ESP32-S3 外挂的 Flash 和 PSRAM 就走 QSPI,高配版甚至用 Octal(8 线)。你
#include进来的代码、跑在 PSRAM 里的大数组,底层都是它在搬。
另一个提速关键是 DMA。刷一整屏彩色数据几万字节,如果让 CPU 一个字节一个字节喂给 SPI,CPU 就全卡在这儿了。ESP32 的 SPI 支持 DMA:你把整块缓冲区的地址交给它,硬件自己边传边取,CPU 腾出手干别的。所以驱动大彩屏一定要开 DMA,否则帧率上不去、界面发卡。"同样一块屏,别人刷得顺你却卡",十有八九就是没走 DMA。
实际接彩屏你还会多看到一两根线:DC(数据/命令选择) 告诉屏幕这一帧发的是命令还是像素,RST(复位) 上电时给它一个复位脉冲。它们不属于 SPI 协议本身,是屏幕这类器件额外要的控制脚,照着模块丝印一一对上即可。很多只写不读的屏幕干脆不接 MISO,最后 SPI 就剩三根加这两根控制线。
一句话口诀
SPI 是四线全双工的高速同步总线:SCLK 打节拍、MOSI 发、MISO 收、CS 低电平点名(一从一根,多用普通 GPIO)。快在收发同时进行加时钟能拉高,代价是费引脚。接不上先查 mode 0~3 对不对,别急着拆线。传大数据(屏/SD/Flash)用它,省线又不赶时间用 I2C。
更多原理对照回 /principle/,模块接线找 /sensor/。