1. SPI 基础回顾:四线制与时序逻辑
各位同学,咱们正式开始这门课之前,先把 SPI 的老底翻出来晒一晒。你可能会想:“SPI 我熟啊,不就四根线嘛。” 嗯,我当年也是这么想的,直到有一次在产线上被一个时序问题折腾了三天三夜…… 从那以后,我养成了一个习惯:每次调 SPI,先把基础逻辑在脑子里过一遍。
1.1 四线制:每一根线都有脾气
SPI 的全称是 Serial Peripheral Interface,说白了就是「串行外设接口」。它用四根线搞定主从设备之间的数据交换。我习惯把这四根线分成两组:
- 时钟和控制线:SCK(时钟)、CS(片选)
- 数据线:MOSI(主出从入)、MISO(主入从出)
你想想看,这四根线各司其职,少一根都不行。我见过有人为了省一个 GPIO,把 CS 直接接地,结果总线上挂了两个从设备,数据乱得一塌糊涂。嗯,这就是典型的「省线不省心」。
| 信号线 | 全称 | 方向(主→从) | 我的理解 |
|---|---|---|---|
| SCK | Serial Clock | 主→从 | 节奏大师,快慢由主决定 |
| MOSI | Master Out Slave In | 主→从 | 主设备说话,从设备听着 |
| MISO | Master In Slave Out | 从→主 | 从设备回话,主设备听着 |
| CS | Chip Select | 主→从 | 叫谁谁答应,低电平有效 |
1.2 主从模式:谁说了算?
SPI 通信里,主设备负责产生时钟信号,从设备只能被动响应。说白了,主设备是老板,从设备是员工。老板什么时候想聊天,员工就得陪着聊。
这里有个关键点:全双工。什么意思?就是老板说话的同时,员工也能回话。你想想看,SCK 每跳一次,主设备往 MOSI 上推一个 bit,同时从设备往 MISO 上推一个 bit。一次时钟沿,两个方向的数据同时完成交换。
核心逻辑:SPI 的每一次数据传输,本质上是一个「交换」过程。主设备发出去一个字节,同时收回来一个字节。如果你只关心发送,那收到的数据可以扔掉;如果你只关心接收,那发送的数据可以是任意值(通常是 0x00 或 0xFF)。
我记得有一次调试一个 ADC 芯片,读出来的数据死活不对。折腾了半天才发现,我发送的指令字节是对的,但后续的 dummy 字节发的是 0x00,而那个 ADC 要求 dummy 必须是 0xFF 才能正确移位。嗯,从那以后,我每次读数据前都会确认一下 dummy 的约定。
1.3 时序逻辑:CPOL 和 CPHA 的恩怨
说到 SPI 时序,绕不开两个参数:CPOL(时钟极性)和 CPHA(时钟相位)。这两个东西决定了数据在什么时刻被采样。
- CPOL = 0:空闲时 SCK 为低电平
- CPOL = 1:空闲时 SCK 为高电平
- CPHA = 0:在第一个时钟沿采样数据
- CPHA = 1:在第二个时钟沿采样数据
两两组合,就得到了四种模式。我刚开始学的时候,总觉得这四种模式记不住。后来我总结了一个土办法:先看空闲电平,再看第一个沿是采样还是切换。
| 模式 | CPOL | CPHA | 空闲 SCK | 采样沿 |
|---|---|---|---|---|
| 模式 0 | 0 | 0 | 低 | 上升沿 |
| 模式 1 | 0 | 1 | 低 | 下降沿 |
| 模式 2 | 1 | 0 | 高 | 下降沿 |
| 模式 3 | 1 | 1 | 高 | 上升沿 |
1.4 全双工通信:同时收发,互不干扰
全双工是 SPI 的一大优势。对比 I2C 的半双工(同一时间只能一个方向传输),SPI 的 MOSI 和 MISO 是独立的物理线路,所以可以同时收发。
你想想看,主设备往 MOSI 上发数据的同时,从设备往 MISO 上发数据。这两个过程在同一个时钟节拍下完成,互不干扰。这也是为什么 SPI 的吞吐量通常比 I2C 高。
但这里有个容易忽略的点:从设备必须在收到指令后,立刻准备好回传数据。如果从设备需要时间处理指令,那它就得在 MISO 上插入等待周期,或者用额外的引脚告诉主设备「我还没准备好」。我遇到过一些老旧的传感器芯片,处理时间长达几十微秒,这时候就必须在 CS 有效之后、发送指令之前,先插入几个 dummy 时钟。
1.5 知识体系总览
下面这张图,是我自己总结的 SPI 基础知识框架。你可以把它当作本章的「思维导图」,后面讲到中断嵌套和优先级配置时,我们会反复回到这些基础概念上。