SPI协议基础:从一根线到四根线的进化

大家好,我是你们的嵌入式讲师。今天咱们聊聊SPI——这个在嵌入式世界里出镜率极高的通信协议。说实话,我刚开始做嵌入式那会儿,SPI给我的感觉就是「快、准、狠」。它不像I2C那样磨叽,也不像UART那样只能点对点。SPI就是那种,你一旦用上就回不去的通信方式。

嗯,咱们先从一个问题开始:为什么需要SPI?

你想想看,早期的设备通信,一根线就够了——比如UART的TX/RX。但问题是,它只能两个人聊天。后来有了I2C,两根线能挂一堆设备,但速度上不去。那如果我想让MCU和ADC、DAC、SD卡、显示屏这些高速设备通信呢?

这时候,SPI就登场了。

SPI总线概述:同步、全双工、主从架构

SPI的全称是Serial Peripheral Interface,串行外设接口。它由摩托罗拉在80年代推出,一直用到现在。核心特点就三个:

  • 同步:有独立的时钟线,收发节奏由时钟控制
  • 全双工:发送和接收可以同时进行
  • 主从架构:一个Master控制多个Slave

我在一个工业数据采集项目里用过SPI,当时MCU要同时读取4个ADC通道的数据。如果用UART,得轮询,速度根本跟不上。换成SPI,一个时钟周期就能把4个通道的数据全部拉回来。那种感觉,就像从绿皮车换成了高铁。

核心概念:SPI的本质是「移位寄存器对移位寄存器」。Master每发出一个时钟脉冲,双方寄存器就交换一个bit。所以SPI的收发是同时发生的——你发出去一个bit的同时,也收到了一个bit。

四线制详解:SCLK、MOSI、MISO、CS

SPI标准四根线,每根线各司其职。我见过不少新手把这四根线接错,结果调了一整天。咱们一个一个说清楚。

信号线 全称 方向 作用
SCLK Serial Clock Master → Slave 时钟信号,由Master产生,决定通信速率
MOSI Master Out Slave In Master → Slave 主设备发送数据到从设备
MISO Master In Slave Out Slave → Master 从设备发送数据到主设备
CS Chip Select Master → Slave 片选信号,低电平有效,选中哪个从设备就拉低哪个

这里有个容易踩的坑:CS线。我见过有人把CS直接接地,觉得「反正就一个设备,不用选了吧?」结果通信时好时坏。为什么?因为CS不仅仅是选设备,它还负责复位从设备的内部状态机。你不拉高拉低CS,从设备可能卡在某个中间状态。

避坑指南:我曾经在一个温湿度传感器项目里,因为CS没有在每次通信前拉高再拉低,导致传感器返回的数据总是错位。后来用示波器一看,CS一直低电平,传感器根本没复位。记住:每次通信前,CS先拉高再拉低,保证从设备状态机复位。

SPI的四种工作模式:CPOL和CPHA

这是SPI最让人头疼的部分,也是面试高频题。说白了,就是时钟的极性(CPOL)和相位(CPHA)怎么搭配。

  • CPOL:时钟空闲时的电平。0=空闲低电平,1=空闲高电平
  • CPHA:数据在哪个时钟沿采样。0=第一个跳变沿采样,1=第二个跳变沿采样

两两组合,就是四种模式:

模式 CPOL CPHA 空闲时钟电平 数据采样沿
模式0 0 0 低电平 上升沿
模式1 0 1 低电平 下降沿
模式2 1 0 高电平 下降沿
模式3 1 1 高电平 上升沿

我个人习惯,90%的传感器和ADC都工作在模式0。但这不是绝对的。我遇到过一款加速度计,它偏偏要用模式3。当时没看数据手册,直接按模式0初始化,读出来的数据全是0xFF。折腾了两小时,才发现是模式不匹配。

经验之谈:拿到一个新器件,第一件事就是看数据手册里的时序图。图上会明确标出CPOL和CPHA。别猜,别试,直接看手册。我吃过这个亏,所以现在每次都会先确认时序图。

下面这张图,把四种模式的时序关系画清楚了:

SPI四种工作模式时序对比 模式0 (CPOL=0, CPHA=0) 空闲低电平,上升沿采样 ↑ 采样 ↑ 采样 ↑ 采样 ↑ 采样 ↑ 采样 ↑ 采样 模式1 (CPOL=0, CPHA=1) 空闲低电平,下降沿采样 ↓ 采样 ↓ 采样 ↓ 采样 ↓ 采样 ↓ 采样 ↓ 采样 模式2 (CPOL=1, CPHA=0) 空闲高电平,下降沿采样 ↓ 采样 ↓ 采样 ↓ 采样 ↓ 采样 ↓ 采样 ↓ 采样 模式3 (CPOL=1, CPHA=1) 空闲高电平,上升沿采样 ↑ 采样 ↑ 采样 ↑ 采样 ↑ 采样 ↑ 采样 ↑ 采样 如何快速判断模式? 1. 看空闲时钟电平:低→CPOL=0,高→CPOL=1 2. 看采样沿:第一个跳变沿采样→CPHA=0,第二个→CPHA=1 3. 最常用的是模式0(CPOL=0, CPHA=0),其次是模式3

SPI与I2C、UART的对比:谁更适合你的项目?

很多初学者会问:这三种协议到底选哪个?我的回答是:看场景。没有最好的协议,只有最合适的协议。

我整理了一个对比表,你一看就明白:

特性 SPI I2C UART
线数 4线(SCLK/MOSI/MISO/CS) 2线(SCL/SDA) 2线(TX/RX)
通信方式 同步全双工 同步半双工 异步全双工
速度 极高(可达几十MHz) 中等(标准100kHz/400kHz/1MHz) 较低(通常115200bps~几Mbps)
多设备支持 每设备一根CS线 7位/10位地址,最多挂128个 点对点,不支持多设备
硬件复杂度 低(无地址、无应答) 中(需地址仲裁) 低(无时钟线)
典型应用 ADC/DAC/显示屏/SD卡/传感器 EEPROM/温湿度传感器/RTC GPS模块/蓝牙模块/调试串口

我个人选型的原则很简单:

  • 要速度?选SPI。比如ADC采集、显示屏刷新、SD卡读写
  • 要省引脚?选I2C。比如挂一堆传感器,MCU引脚不够用
  • 要简单?选UART。比如和PC通信、接个GPS模块

实战建议:在一个项目中,我同时用了SPI和I2C。SPI接高速ADC,I2C接温湿度传感器和RTC。这样既保证了采集速度,又节省了引脚。说白了,混用才是常态。

SPI的局限性:不是万能药

说了SPI这么多好处,也得说说它的短板。我遇到过不少项目,SPI用得挺爽,但后来发现几个问题:

  • 引脚占用多:每加一个从设备,就要多一根CS线。挂8个设备,光CS就占8个GPIO
  • 没有应答机制:Master发出去的数据,Slave收到没有?SPI不告诉你。你得自己加校验
  • 没有流控:Slave处理不过来怎么办?SPI没有硬件流控,只能靠软件延时
  • 距离受限:SPI不适合长距离传输。超过几十厘米,信号就容易出问题

避坑指南:我曾经在一个项目中,把SPI线拉到了1米长。结果通信时好时坏,用示波器一看,时钟信号已经严重畸变。后来加了电平转换芯片,把差分信号传过去,才解决问题。记住:SPI是板级通信协议,别拿来当总线用。

小结:SPI的核心要点

好了,这一章的内容就到这里。咱们回顾一下核心要点:

  • SPI是同步全双工通信,四根线各司其职
  • 四种工作模式由CPOL和CPHA决定,模式0最常用
  • CS线必须每次通信前复位,否则从设备可能卡死
  • SPI速度快、硬件简单,但引脚占用多、没有应答机制
  • 选型时根据速度、引脚、距离综合判断