1. 课程导入与无人机姿态问题

大家好,我是你们这门课的老朋友。今天咱们聊聊SPI——这个在嵌入式世界里出镜率极高的串行接口。说实话,我做了十几年嵌入式开发,SPI是我用得最多的协议之一。它不像I2C那么“啰嗦”,也不像UART那么“随意”,SPI给我的感觉就是——干脆、利落、速度快。

你可能会问:为什么需要SPI?想想看,如果你要驱动一个高速ADC,或者刷新一块OLED屏幕,UART那点速度根本不够看。I2C虽然能挂多个设备,但总线仲裁和应答机制拖慢了节奏。这时候,SPI就站出来了。

核心认知:SPI是一种全双工、同步、主从式的串行通信协议。它用四根线解决了“谁说话、什么时候说话、说什么、说多快”这四个通信核心问题。

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

SPI的四根线,每一根都有明确的职责。我刚开始学的时候,总觉得这四根线名字绕口,后来发现——记住它们的英文全称,就再也不会搞混了。

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

这里有个细节我特别想强调:CS线是SPI多设备通信的关键。我在一个项目里遇到过这样的问题——两个从机共用一组SCLK/MOSI/MISO,但CS线没处理好,结果一个设备在发送数据时,另一个设备也在“偷听”,导致总线冲突。嗯,从那以后,我每次画原理图都会再三确认CS的拉高拉低时序。

个人经验:我习惯在CS线上加一个10kΩ上拉电阻,确保系统上电时从机处于非选中状态。这个习惯帮我避免了好几次“莫名其妙”的通信失败。

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

SPI的四种模式,说白了就是时钟极性(CPOL)和时钟相位(CPHA)的排列组合。很多初学者在这里栽跟头,我当年也是。

先理解两个概念:

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

组合起来就是四种模式:

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

你可能会问:这么多模式,到底用哪个?我个人的建议是:先看从机数据手册。大多数SPI外设默认支持模式0或模式3。我做过一个项目,用STM32驱动一个MEMS加速度计,数据手册上写的是“模式3”,我一开始没注意,用了模式0,结果读出来的数据全是乱的。查了两天才发现是模式不匹配。

避坑指南:我曾经在一个量产项目中,因为主控和从机的SPI模式配置不一致,导致部分批次的产品通信不稳定。后来我在驱动初始化代码里加了一段自动检测逻辑——先发一个已知字节,根据回读数据判断当前模式是否正确。这个技巧后来成了我SPI驱动开发的标配。

SPI与I2C/UART的对比

很多初学者会问:这三种协议到底怎么选?我做个表格,一目了然。

特性 SPI I2C UART
线数 4线(全双工) 2线(半双工) 2线(全双工)
速度 最高可达几十MHz 标准100kHz/400kHz,高速3.4MHz 通常115200bps~几Mbps
通信方式 同步(有时钟线) 同步(有时钟线) 异步(无时钟线)
多设备支持 每设备一根CS线 通过地址区分,最多127个 点对点,多设备需额外协议
硬件复杂度 中等 低(开漏输出需上拉) 低
典型应用 ADC/DAC、显示屏、SD卡、传感器 EEPROM、温湿度传感器、RTC GPS模块、蓝牙模块、调试串口

说说我的选择逻辑:

  • 要速度?选SPI。 比如驱动一个320×240的LCD,刷新率60fps,用SPI轻松搞定,I2C就吃力了。
  • 要省引脚?选I2C。 一个项目里挂了5个传感器,I2C只需要两根线,SPI得6根线起步。
  • 要简单?选UART。 和PC通信、调试输出,UART最方便,随便一个串口助手就能看数据。

我的经验法则:如果设备需要高速、连续的数据传输(比如音频、视频、传感器数据流),SPI是首选。如果设备只是偶尔读写几个字节的配置信息(比如EEPROM、RTC),I2C更合适。UART则适合设备间简单、低速的通信,尤其是和PC交互。

SPI通信的核心流程

说了这么多理论,咱们看看SPI通信到底是怎么跑的。我画了一张流程图,帮你理清思路。

SPI通信核心流程 主机(Master) ① 拉低CS,选中从机 CS = 0,从机进入通信状态 ② 产生SCLK时钟 SCLK按设定频率开始翻转 ③ 数据收发同时进行 MOSI:主机发送数据 → 从机接收 MISO:从机发送数据 → 主机接收 ④ 传输完成,拉高CS CS = 1,从机释放总线 通信结束

这个流程看起来简单,但有几个关键点要注意:

  • CS的拉高拉低时机:必须在SCLK稳定之后才能拉低CS,传输完成后也要等最后一个数据位采样完毕再拉高。我见过有人把CS和SCLK的时序搞反,结果数据错位。
  • 数据是同时收发的:SPI是全双工,主机发一个字节的同时,从机也在发一个字节。如果你只关心接收数据,也得发送一个“虚拟字节”(通常是0x00或0xFF)。
  • 时钟频率不是越高越好:从机有最大时钟限制,PCB走线也有信号完整性约束。我一般先看数据手册,再留20%的余量。

调试技巧:用逻辑分析仪抓SPI波形时,先抓CS和SCLK的时序关系,确认模式配置正确。然后再看MOSI/MISO的数据是否对齐。我习惯在发送第一个字节时发0x55(二进制01010101),这样从波形上能直观看到每一位的变化。

SPI的变体与扩展

标准的四线制SPI已经很强大了,但实际项目中还有一些变体:

  • 三线制SPI:把MOSI和MISO合并成一根双向数据线。省了一根线,但牺牲了全双工能力。我一般在引脚紧张的MCU上才用。
  • 双线制SPI:只有SCLK和双向数据线,常用于一些简单的传感器。
  • 多从机SPI:每个从机独立CS线,或者用菊花链方式串联。菊花链我用的不多,因为一旦中间某个设备出问题,整条链都受影响。
  • QSPI/OSPI:四线/八线SPI,数据线从1根扩展到4根或8根,速度翻倍。我在驱动高速NOR Flash时用过QSPI,确实快。

嗯,SPI协议的基础就聊到这里。记住一句话:SPI的核心是“主控节奏,从机响应”。后面的章节我们会深入具体的驱动开发,到时候你会看到这些基础知识是怎么落地的。