1. SPI协议基础:从起源到全双工通信
SPI,全称是Serial Peripheral Interface,串行外设接口。这玩意儿是摩托罗拉在80年代搞出来的,初衷很简单——让微控制器能快速跟外设芯片交换数据。我最早接触SPI是在做一款工业传感器采集板的时候,那时候I²C速度跟不上,UART又太浪费引脚,SPI正好卡在中间,又快又灵活。
说白了,SPI就是一条四线制的同步串行总线。同步的意思是,它靠时钟来对齐数据,不像UART那样需要两边约定好波特率。这一点在实际调试中特别省心——你只要把时钟线接对,数据基本不会跑偏。
四线制到底在传什么?
SPI的四根线,每一根都有明确的职责。我见过不少新手把这四根线搞混,结果焊完板子发现通信死活不通。咱们一个一个说清楚。
| 信号线 | 全称 | 方向 | 一句话职责 |
|---|---|---|---|
| SCLK | Serial Clock | 主机→从机 | 提供同步节拍,决定通信速率 |
| MOSI | Master Out Slave In | 主机→从机 | 主机发数据给从机 |
| MISO | Master In Slave Out | 从机→主机 | 从机发数据给主机 |
| CS | Chip Select | 主机→从机 | 片选信号,低电平有效,选中谁就跟谁聊 |
这里有个容易踩的坑——MOSI和MISO的名字已经说清楚了方向。MOSI是主机输出、从机输入;MISO是主机输入、从机输出。我曾经遇到过一块板子,硬件工程师把这两根线画反了,结果主机发出去的数据从机收不到,从机回的数据主机也读不到。查了整整半天才找到原因。
全双工通信——同时收发才是SPI的灵魂
SPI最让我欣赏的一点,就是它天生支持全双工。什么叫全双工?就是主机在发数据的同时,从机也在往回发数据。一根时钟线,两个方向的数据流,互不干扰。
你想想看,UART虽然也能全双工,但它需要两根独立的数据线,而且两边得各自约定波特率。I²C更惨,它是半双工的,发的时候不能收,收的时候不能发。SPI就不一样了——一个时钟周期内,MOSI上走一位数据给从机,MISO上同时走一位数据回主机。
为什么会这样?因为SPI本质上是一个环形移位寄存器。主机和从机内部各有一个移位寄存器,时钟每跳一次,两个寄存器同时移一位。主机移出去的数据进了从机,从机移出去的数据进了主机。就这么简单。
核心理解:SPI的每一次时钟跳变,都是一次数据交换。主机发出去一个bit,同时收回一个bit。所以从软件角度看,你调用SPI发送函数时,收到的返回值其实就是从机发给你的数据。
我记得有一次调试一个ADC芯片,手册上说读数据之前要先发一个命令字节。我按常规思路先发命令,再单独读数据,结果读回来的全是0。后来仔细看时序图才发现——发命令的那个时钟周期里,ADC已经把转换结果的高位发回来了。我等于把有效数据扔了。从那以后,我写SPI驱动时都会记住:每一次SPI读写,都是同时发生的。
SPI的四种模式——时钟极性那点事
SPI有四种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)组合决定。这俩参数搞错了,通信就会出乱码。我见过最离谱的一次,是两边的工程师各用各的默认模式,结果数据对不上,互相甩锅。
| 模式 | CPOL | CPHA | 时钟空闲电平 | 数据采样边沿 |
|---|---|---|---|---|
| 模式0 | 0 | 0 | 低电平 | 上升沿采样 |
| 模式1 | 0 | 1 | 低电平 | 下降沿采样 |
| 模式2 | 1 | 0 | 高电平 | 下降沿采样 |
| 模式3 | 1 | 1 | 高电平 | 上升沿采样 |
实际项目中,绝大多数SPI器件默认用模式0。但千万别想当然——我吃过一次亏,某款国产加速度传感器手册上写的是模式3,我没仔细看,直接用模式0驱动,数据读出来全是乱码。后来用逻辑分析仪抓波形才发现,时钟空闲电平不对。
SPI通信的核心流程
一次完整的SPI传输,大致分三步:
- 拉低CS——告诉从机:我要跟你说话了。
- 产生SCLK时钟——每来一个时钟,MOSI和MISO上各走一位数据。通常是高位在前(MSB first),但也有少数器件用低位在前。
- 拉高CS——传输结束,从机释放总线。
这里有个细节:CS拉低期间,时钟可以连续产生,也可以间断。有些器件要求CS拉低后必须连续发完一整个字节,中间不能停;有些则无所谓。嗯,这个得看具体芯片的手册。
下面这张图是我自己画的SPI全双工通信流程,帮你把整个数据流动看清楚。
SPI的优缺点——没有银弹
SPI不是万能的。它有自己的长处,也有明显的短板。我列个表,你一看就明白。
| 优势 | 劣势 |
|---|---|
| 全双工,收发同时进行 | 需要4根线,引脚占用多 |
| 传输速率高,轻松上几十MHz | 没有内置应答机制,丢数据不知道 |
| 硬件实现简单,软件驱动容易 | 多从机时需要额外CS引脚 |
| 支持多从机级联(菊花链) | 传输距离短,一般不超过几米 |
我个人觉得,SPI最适合的场景是:板上通信、高速数据采集、显示驱动、存储器读写。如果你要做长距离传输或者需要多设备总线仲裁,那还是考虑CAN或者RS-485更靠谱。
一句话总结:SPI用四根线、一根时钟、全双工、主从结构,实现了简单高效的短距离高速通信。理解它的四线职责和全双工原理,是后面调试多设备级联的基础。