2、SPI总线协议基础:从物理层到实战对比

大家好,我是你们的嵌入式Linux驱动讲师。今天我们来聊聊SPI总线协议的基础知识。说实话,SPI和I2C是我在驱动移植工作中打交道最多的两种总线。很多初学者觉得SPI协议简单,不就是四根线嘛——但真正到了调试阶段,各种坑就冒出来了。

我个人习惯把SPI协议拆成四个维度来理解:物理层长什么样、时钟极性怎么配、时序怎么分析、以及它和I2C到底有啥区别。咱们一个一个来。

2.1 SPI物理层特性

SPI的全称是Serial Peripheral Interface,串行外设接口。它由Motorola公司提出,后来成了事实上的工业标准。

物理层信号线

  • SCLK(Serial Clock):主设备产生的时钟信号
  • MOSI(Master Out Slave In):主设备输出,从设备输入
  • MISO(Master In Slave Out):主设备输入,从设备输出
  • SS/CS(Slave Select/Chip Select):片选信号,低电平有效

嗯,这里要注意:SPI是全双工通信。什么意思?就是发送和接收可以同时进行。这一点和I2C完全不同,I2C是半双工的,同一时间只能一个方向传数据。

我在项目中遇到过一个问题:某款ADC芯片的MISO引脚在片选拉高后没有进入高阻态,导致多个从设备共用MISO线时产生冲突。后来我加了一个三态缓冲器才解决。所以大家设计多从设备SPI总线时,一定要确认从设备的MISO是否支持高阻态输出。

关键参数速查

  • 最大速率:通常10MHz~50MHz,高速器件可达100MHz+
  • 通信距离:板级通信(几厘米到几十厘米),远距离需加驱动
  • 从设备数量:理论上无限,但受限于片选引脚和负载电容
  • 数据格式:MSB First(大多数器件)或LSB First

2.2 SPI四种工作模式(CPOL/CPHA)

这是SPI协议里最容易搞混的地方。我刚开始学的时候也绕了好一阵子。说白了,就是时钟极性(CPOL)和时钟相位(CPHA)的组合。

CPOL:时钟极性。决定SCLK空闲时的电平。

  • CPOL=0:空闲时SCLK为低电平
  • CPOL=1:空闲时SCLK为高电平

CPHA:时钟相位。决定数据在哪个时钟沿采样。

  • CPHA=0:第一个时钟沿采样(上升沿或下降沿取决于CPOL)
  • CPHA=1:第二个时钟沿采样

组合起来就是四种模式:

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

我的记忆口诀:模式0和模式3最常用。模式0是"空闲低、上升采",模式3是"空闲高、上升采"。你想想看,大多数SPI Flash和传感器都默认用模式0或模式3。

我曾经踩过一个坑:某款温湿度传感器手册上写支持"SPI模式0",但我用模式3也能通信。后来仔细看时序图才发现,它其实对时钟沿不敏感,只要保证建立时间和保持时间就够了。但这种情况很少见,千万不要赌,一定要按手册配。

2.3 SPI总线时序分析

时序分析是驱动移植的核心能力。说白了,就是看波形图,搞清楚数据什么时候被采样、什么时候被输出。

我们以最常用的模式0为例:

SCLK:  ▔▁▔▁▔▁▔▁▔▁▔▁▔▁▔▁
       ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
       │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
       └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘

MOSI:  ──┐   ┌───┐   ┌───┐   ┌───┐   ┌──
         └───┘   └───┘   └───┘   └───┘
         bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0

MISO:  ──┐   ┌───┐   ┌───┐   ┌───┐   ┌──
         └───┘   └───┘   └───┘   └───┘
         bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0

采样点:    ↑     ↑     ↑     ↑     ↑     ↑     ↑     ↑

看到没?在模式0下,数据在SCLK的上升沿被采样,在下降沿被更新。主设备在下降沿把数据放到MOSI上,从设备在上升沿读取。反过来,从设备在下降沿把数据放到MISO上,主设备在上升沿读取。

这里有个关键点:建立时间(tSU)和保持时间(tHD)。数据必须在采样沿之前稳定下来,并且在采样沿之后保持一段时间。不同器件的时序要求不一样,我建议你在移植驱动时,一定要去查数据手册里的时序参数表。

避坑指南:我曾经在移植一款LCD驱动时,发现显示偶尔出现花屏。用示波器一抓,发现SCLK频率太高,导致数据建立时间不足。把时钟从20MHz降到10MHz,问题就解决了。所以,不要一味追求高速,稳定才是第一位的。

2.4 SPI与I2C对比

很多初学者会问:什么时候用SPI,什么时候用I2C?我的回答是:看需求。

下面这张表是我自己总结的,你可以收藏一下:

对比项 SPI I2C
信号线数量 4根(SCLK, MOSI, MISO, CS) 2根(SCL, SDA)
通信方式 全双工 半双工
传输速率 通常10~50MHz,可达100MHz+ 标准100kHz,快速400kHz,高速3.4MHz
从设备寻址 片选信号(硬件寻址) 7位或10位地址(软件寻址)
总线冲突 无(片选独立) 需要仲裁机制
从设备数量 受限于片选引脚 理论上127个(7位地址)
硬件复杂度 简单,无上拉电阻 需要上拉电阻,有开漏输出
典型应用 Flash、ADC/DAC、LCD、传感器 EEPROM、温度传感器、RTC

我个人习惯这样选型:

  • 需要高速传输(>1MHz)→ 选SPI
  • 需要全双工通信 → 选SPI
  • 引脚资源紧张 → 选I2C
  • 需要挂载大量从设备 → 选I2C
  • 对实时性要求高 → 选SPI(I2C有仲裁延迟)

你想想看,为什么SPI Flash那么普遍?因为SPI的速率可以轻松跑到几十兆,而I2C的EEPROM最多也就几兆。但反过来,为什么很多传感器用I2C?因为传感器数据量小,两根线就能搞定,省引脚。

核心结论:SPI是"速度优先"的协议,I2C是"引脚优先"的协议。没有谁好谁坏,只有谁更合适。

2.5 本章知识体系总览

下面这张SVG图是我画的,把SPI协议基础的核心逻辑串起来了。你可以把它当作一个思维导图来用。

SPI总线协议基础 物理层特性 • 4线:SCLK, MOSI, MISO, CS • 全双工通信 • 主从架构 • 速率:10~100MHz 四种工作模式 • CPOL:时钟极性 • CPHA:时钟相位 • 模式0/1/2/3 • 模式0和3最常用 时序分析 • 采样沿 vs 输出沿 • 建立时间 tSU • 保持时间 tHD • 示波器实测验证 SPI vs I2C 对比 • SPI:速度优先,4线全双工 • I2C:引脚优先,2线半双工 • 选型:看速率和引脚需求 核心:理解物理层 → 配对模式 → 验证时序

这张图把SPI协议基础的四个维度串在了一起。你从物理层入手,理解四根线怎么接;然后配置CPOL/CPHA,选对工作模式;接着用示波器抓时序,验证建立时间和保持时间;最后根据项目需求,决定用SPI还是I2C。

好了,这一章的内容就到这里。SPI协议基础是驱动移植的基石,你把它吃透了,后面移植SPI Flash、SPI LCD、SPI传感器的时候就会轻松很多。


专注资料整理