第八课时:SPI 总线结构
本课主题:SPI 总线结构,也就是串行外设接口的基础知识。
课程视频:SPI 总线结构(视频链接待补充)
一、基本知识介绍

SPI 是 Serial Peripheral Interface 的缩写,中文叫串行外设接口,适用于高速、双向数据传输的场景。

先认识一个典型器件,W25QXX 系列 Flash 模块,板子上引出 DI、CLK、GND、DO、CS、VCC 几个引脚,后面读写数据就靠它。
图片:Pasted image 20261005115334.png
SPI 由四条线组成。MOSI 是主机输出、从机输入;MISO 是从机输出、主机输入;SCK 是串行时钟线,由主机产生;NSS 是从机选择,也叫片选,每个从机一根。主机这边可以有 NSS1、NSS2、NSS3 多根片选,分别对到不同的从机。

MOSI 全称 Master Output Slave Input,拆开就是主机、输出、从机、输入,也就是主机发送、从机接收。

比如主机要把 100 这个字节发出去,就在 MOSI 上按位送出。因为多个从机共用 MOSI,具体发给谁要靠片选决定,图里数据线同时连到三个从机,谁被选中就归谁收。

SCK 全称 Serial Clock,也就是串行时钟线,负责给出位传输的节拍。

NSS 全称 Negative Slave Select,从机选择,低电压有效。主机把某个从机的 NSS 拉低,就代表选中它。

重点来了,SPI 是全双工的,MOSI 在向从机发送数据的同时,MISO 也会向主机发送数据。图左边,主机通过 MOSI 给从机 1 发一个字节,比如 100,同时从机也通过 MISO 给主机回一个字节,这个字节是什么要从机说了算。图右边把几条线的时序画了出来:NSS1 拉低选中从机 1,SCK 给出 8 个时钟,MOSI 上是 01100100,也就是 100,MISO 上是从机回的 11001010,也就是 0xCA。
这是数据出现的基本原则,但它很容易引出下面几个问题。
1.1 我的疑问
- 那从机向主机发送的数据代表什么呢?
- 因为 SPI 是高位先行,从机默认数据的高位要往前移,给主机发送的数据让位,无用高位就发送给主机,这句话的意义是什么?
- SPI 总线可以理解为是 I2C 总线的"富哥版本",I2C 是半双工、SPI 是全双工,这样的说法对吗?
1.2 疑问解答
- 从机发给主机的数据代表什么
SPI 是全双工的,主机通过 MOSI 往从机推数据的同时,从机也在通过 MISO 往主机推数据,所以你在"发"的时候,必然会收到从机发来的数据。这些数据代表什么,由从机也就是外设自己决定,要去查它的数据手册。一般有几种情况:主机先发命令或地址,从机就把对应的数据返回,Flash 和传感器都是这样;从机也可能返回状态字,比如忙不忙、有没有出错;如果此刻从机没有有意义的数据,它会返回占位数据,也就是 dummy,主机直接忽略即可。
关键一点,SPI 本身不规定数据的含义,它只负责一个时钟换一位,含义由两端芯片约定。
- "高位先行 / 往前移让位 / 无用高位"这句话的意义
SPI 两端各有一个移位寄存器。SCK 每来一个脉冲,主机把最高位先移出去放到 MOSI,这就是高位先行;同时从机也把自己寄存器的最高位移到 MISO 上,两位数据同时交换。
所以"往前移让位"说的是硬件自动完成的事,数据是移出去一位、同时移进来一位,移出去的位腾出的空位正好被移进来的位填上,就像两个人各拿一串珠子,同时往对方手里推一颗。让位不用你操心,硬件会做。
"无用高位就发送给主机"是说,当从机没有有意义的数据要发时,比如主机只是在写命令,从机 MISO 上移出来的就是没用的占位数据,主机收到丢掉即可。
一句话,SPI 靠移位寄存器加时钟来同步收发,每个时钟自动移出一位、移进一位,收到的没意义的数据就是 dummy。
- "SPI 是 I2C 的富哥版本"这个说法对吗
"I2C 半双工、SPI 全双工"这句话是对的。I2C 只有一根数据线 SDA,同一时刻只能一个方向传,要么写要么读,是半双工;SPI 有 MOSI 和 MISO 两根数据线,可以同时收发,是全双工。
但"SPI 是 I2C 的富哥版本"这个说法不严谨,它们是两种不同的总线,各有取舍:
| 对比 | I2C | SPI |
|---|---|---|
| 线数 | 2 根(SCL、SDA) | 至少 4 根(SCK、MOSI、MISO、CS) |
| 怎么选从机 | 靠地址,不用额外线 | 靠片选 CS,每个从机一根 |
| 双工 | 半双工 | 全双工 |
| 速度 | 慢一些,100k 到几 MHz | 快,几十 MHz |
| 应答机制 | 有 ACK / NAK | 没有应答 |
| 多主机 | 支持,有仲裁 | 一般是一主多从 |
结论:SPI 换来了速度和全双工,代价是引脚多,每加一个从机就多一根片选,而且没有地址和应答机制。不是谁更高级,而是场景不同。
二、SPI 总线的 5 个参数

SPI 有五个参数:波特率、比特位传输顺序、数据位长度、时钟的极性和时钟的相位。
先说波特率。

波特率通常代表着速度,也就是每秒钟传输高低电压的数量。SPI 总线没有规定波特率的范围,一般取几兆到几十兆 bps。

波特率的选取原则是,选择允许的最大值。这个最大值要看两边:设备能承受的极限,比如这块 W25QXX,不超过 80Mbps;电路板能承受的极限,比如这块板子不超过 10Mbps。两个限制取小的那个,所以这里最终取 10Mbps。
接着说比特位传输顺序。

一个无符号 8 位整数,从右边数 bit0 是最低有效位,也就是 LSB,从左边数 bit7 是最高有效位,也就是 MSB。比如十进制 99,二进制是 01100011。MSB First 是先传最高有效位,从 bit7 往 bit0 传;LSB First 是先传最低有效位,反过来传。SPI 是高位先行,默认就是 MSB First。
然后是数据位长度。

数据位长度可以是 8 位或者 16 位。发送一个较长的数据时,上下两个波形其实有些一样,区别在于怎么拆分。8 位一组,每组一个字节,0xb51f 就拆成 {0xb5, 0x1f} 两个字节;16 位一组,0xb51f 就是一个 16 位整数,一次传完。
接着是时钟的极性,也就是 CPOL。

时钟极性决定空闲时 SCK 停在低电平还是高电平。极性等于低,空闲状态是低电压,第一个边沿是上升沿;极性等于高,空闲状态是高电压,第一个边沿是下降沿。
最后是时钟的相位,也就是 CPHA。

把波形截取展开,能把数据的收发分解成发送和采集两个环节。看下面的展开图,每个时钟周期里有一段用来发送,有一段用来采集,采集的时刻数据必须稳定,发送的时刻才去改变它。记法就是,电压拉高拉低就是发送,维持不变就是采集。

相位决定在哪个边沿采集。第一边沿采集,是在第一个边沿就把数据采走;第二边沿采集,是在第二个边沿采。
四种时钟模式,就是把极性和相位组合起来。

极性低、第一边沿采集是模式 0;极性低、第二边沿采集是模式 1;极性高、第一边沿采集是模式 2;极性高、第二边沿采集是模式 3。
2.1 我的疑问
- 这四种模式有什么区别?
- 第一边沿、第二边沿相互之间会有什么意义?
- 不同的极性又有什么意义?
- 区分以上这些的应用场景在哪里?
2.2 疑问解答
先说结论,这四个问题其实都绕着 CPOL(极性)乘以 CPHA(相位)等于 4 种模式这一点转。
- 四种模式有什么区别
SPI 的 4 种模式就是 CPOL 和 CPHA 的 4 种组合,区别只在这两件事上:CPOL 决定空闲时 SCK 停在低还是高;CPHA 决定数据在第几个边沿被采样,第一个还是第二个。传数据的本质完全一样,每个时钟移出一位、移进一位。但要注意,主从双方必须用同一种模式,否则采样时刻错位,数据全错。
| 模式 | CPOL(空闲电平) | CPHA(第几个边沿采样) | 采样沿 |
|---|---|---|---|
| Mode 0 | 0(空闲低) | 0(第一个边沿) | 上升沿 |
| Mode 1 | 0(空闲低) | 1(第二个边沿) | 下降沿 |
| Mode 2 | 1(空闲高) | 0(第一个边沿) | 下降沿 |
| Mode 3 | 1(空闲高) | 1(第二个边沿) | 上升沿 |
- 第一边沿、第二边沿相互之间有什么意义
一个时钟周期有两个边沿,第一个边沿是从空闲电平跳出去,第二个边沿是跳回空闲电平。SPI 的规矩是,一个边沿用来改变或发送数据,另一个边沿用来采样数据,收发错开,谁也不撞谁。CPHA 等于 0 时,第一个边沿采样,之后才改变数据;CPHA 等于 1 时,第二个边沿采样,第一个边沿先改变数据。前面记的"电压拉高拉低就是发送,维持不变就是采集"正好对上这条,采样边沿上数据必须稳定不变,改变只发生在另一个边沿。
- 不同的极性有什么意义
CPOL 只决定一件事,空闲时 SCK 停在低还是高。它本身不改数据,只是让第一个边沿的方向不同:CPOL 等于 0,空闲低,第一个边沿是上升沿;CPOL 等于 1,空闲高,第一个边沿是下降沿。它的意义在于迁就从机,不少器件要求时钟线空闲时停在某个固定电平,来配合它内部的逻辑,所以 SPI 把极性做成可配置。配错了,边沿方向反了,采样时刻就错,收不到正确数据。
- 这些区别用在哪里
看从机的手册。器件数据手册里会写它支持的 SPI 模式,也就是 Mode 0 到 3,或者直接写 CPOL、CPHA 的值,照着配就行。常见情况是,Flash,比如 W25Qxx,以及 SD 卡的 SPI 模式,常用 Mode 0;一些传感器、ADC、显示屏用 Mode 1 或 Mode 3,以手册为准。在 CubeMX 里就是 SPI 配置页的 Clock Polarity 和 Clock Phase 两项。两端模式不一致,是最常见的 SPI 收不到数据的原因。
复习速记
- SPI 是串行外设接口,全双工,MOSI 主到从和 MISO 从到主可以同时收发。
- "SPI 是 I2C 的富哥版本"不严谨,但"I2C 半双工、SPI 全双工"是对的。
- SPI 的代价是每个从机要一根独立片选 CS,而且没有地址、没有应答。
- 收数据时必然会收到从机发来的东西,没意义的是 dummy,常见是 0xff,忽略即可。
- 高位先行,也就是 MSB first;移位寄存器每个时钟移出一位、移进一位,让位是硬件自动的,不用你管。
- CPOL 是极性,空闲时 SCK 停低 0 或停高 1;CPHA 是相位,第 1 个或第 2 个边沿采样,组合起来共 4 种模式,Mode 0 到 3。
- 主从双方模式必须一致,不一致就收不到数据,CubeMX 里对应 Clock Polarity 和 Clock Phase。
- 五个参数:波特率、位序、数据位长度、CPOL、CPHA。