【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集

前言

SPI 是嵌入式开发使用频率最高、速度最快的短距离串行通信总线。

Flash、LCD、OLED、SD卡、传感器全部依赖 SPI 通信。

很多同学只会 HAL 库调用,不懂底层移位原理、不懂四种时钟模式本质、不懂寄存器分工、不懂主从真实数据流向。

本篇文章一次性讲透 SPI 所有必考底层知识 + 工程细节 + 面试考点。

一、SPI 核心通信特性(面试必背)

  1. 同步通信

SPI 属于同步串行通信。

同步含义:

收发双方共用同一个时钟信号 SCLK,所有数据采样、移位全部跟随时钟边沿。

对比:

  • USART 异步:双方各自时钟,不需要时钟线
  • SPI 同步:主机提供时钟,从机严格跟随主机时钟
  1. 全双工通信(SPI 最大特点)

SPI 天然全双工,收发同时进行,互不冲突。

底层本质:

主机移位寄存器 和 从机移位寄存器,在每个时钟边沿互相交换 1bit 数据。

每一个 SCLK 脉冲同时完成两件事:

  1. 自己移出一位数据发出去
  2. 对方移入一位数据收进来

这就是 SPI 为什么速度快、为什么天生全双工 的根本原因。

  1. 串行通信

数据逐比特移位传输,不是并行一次性传输。

二、SPI 四线硬件结构(标准 SPI)

标准 SPI 一共 4 根线,功能完全固定:

  1. SCLK 时钟线
  • 由主机产生
  • 从机完全被动跟随时钟
  • 决定通信速率、采样边沿
  1. MOSI 主机输出、从机输入
  • Master Out Slave In
  • 主机 → 从机 数据通道
  1. MISO 主机输入、从机输出
  • Master In Slave Out
  • 从机 → 主机 数据通道
  1. CS / NSS 片选线
  • 低电平选中对应从机
  • 一从机一CS线
  • 未选中时,从机 MISO 为高阻态,不占用总线

补充:三线 SPI 是省略 CS / NSS ,工程基本不用。

三、SPI 主从架构(一主多从)

  1. 拓扑结构
  • 唯一主机:STM32 单片机
  • 多个从机:Flash、OLED、传感器、其他MCU
  1. 总线特点
  • SCLK、MOSI、MISO 所有从机共用
  • CS 独立独占,每个从机单独一根片选
  1. 工作逻辑

  2. 主机拉低某个从机的 CS

  3. 主机输出 SCLK 时钟

  4. 对应被选中的从机开始通信

  5. 未选中从机保持高阻,不响应总线

  6. 优缺点

✅ 优点:

  • 扩展从机极其简单,只需多加一根 CS
  • 通信速度极快

❌ 缺点:

  • 无应答机制
  • 无设备地址,纯靠片选区分设备

四、SPI 数据传输细节

  1. 数据宽度

标准支持:8bit / 16bit

工程 99% 场景使用 8bit 传输

  1. 数据位序:MSB / LSB

SPI 支持两种移位顺序:

  1. MSB 先行(高位先出)
  • 绝大多数外设默认:Flash、OLED、传感器
  1. LSB 先行(低位先出)
  • 极少设备使用,需要手册确认

位序配置错误,数据全部错乱,无法通信

五、SPI 四种工作模式(面试最高频)

SPI 模式由两个寄存器位决定:

  • CPOL 时钟极性
  • CPHA 时钟相位
  1. 时钟极性(Clock Polarity - CPOL)定义了时钟信号在空闲状态(无数据传输时)的电平:

CPOL = 0:时钟空闲时为低电平,如下图所示。

CPOL = 1:时钟空闲时为高电平,如下图所示。

  1. 在理解时钟相位之前,我们先来理解两个概念:第一边沿和第二边沿:
  • 第一边沿:一个有效时钟周期开始时的第一个电平跳变边沿

  • 第二边沿:紧跟第一边沿发生的、方向相反的第二个电平跳变边沿

    比如:

时钟相位(Clock Phase - CPHA)定义了数据在时钟信号的哪个边沿被采样(读取、捕获),哪个边沿允许数据变化(发送),决定了数据位保持稳定和切换的精确时刻。

时钟相位的含义如下:

CPHA = 0:数据在时钟的第一边沿被采样(读取),在第二边沿改变数据位(发送)

CPHA = 1:数据在时钟的第一边沿改变数据位(发送),在第二边沿被采样(读取)

  1. 四种模式对照表

重点工程结论

市面上 80% 的 SPI 设备默认都是 Mode0

六、SPI 底层寄存器架构(核心吃透)

SPI 外设内部真正工作的寄存器分为 三层结构

  1. TX-DR 发送数据缓冲区
  • 软件写入数据的寄存器
  • CPU 把要发送的数据写入 TX-DR
  • 无独立地址,写 DR 自动写入 TX-DR
  1. RX-DR 接收数据缓冲区
  • 存放从机传回的数据
  • 无独立地址,读 DR 自动读取 RX-DR
  1. 移位寄存器(核心工作单元)

真正实现全双工比特交换的硬件

  • 不占用总线地址,软件不可直接操作
  • 每一个时钟完成一次 bit 互换
  1. 对外统一寄存器 DR

手册上只有一个 DR 寄存器:

  • 写 DR → 写入内部 TX-DR
  • 读 DR → 读取内部 RX-DR
  1. 常用关键寄存器

  2. SPI_CR1 控制寄存器1

  • CPOL、CPHA 模式配置
  • 波特率分频
  • MSB/LSB 位序
  • 软件从机管理位
  1. SPI_SR 状态寄存器
  • TXE:发送空
  • RXNE:接收非空
  • OVR:接收溢出(高频错误)
  1. SPI_DR 数据寄存器
  • 唯一数据交互端口

七、SPI 完整一次通信流程(主从全流程)

  1. 主机拉低从机 CS,选中设备
  2. 主机 CPU 写数据到 TX-DR
  3. 数据加载进主机移位寄存器
  4. 主机输出 SCLK 时钟
  5. 主从移位寄存器逐比特互换数据
  6. 8 个时钟结束,收发完成
  7. 移位数据存入各自 RX-DR
  8. CPU 读取 DR 获取从机数据
  9. 主机拉高 CS,结束通信

关键真相:

SPI 读数据必须发数据!

八、SPI 高频面试题(必背)

  1. SPI 是什么通信?

同步、串行、全双工总线。

  1. SPI 为什么是全双工?

主从各有移位寄存器,时钟边沿同时移出、移入,天然收发并行。

  1. 四根线分别作用?

SCLK:主机时钟

MOSI:主发从收

MISO:从发主收

CS:片选选通设备

  1. SPI 四种模式怎么区分?

CPOL 决定空闲电平,CPHA 决定采样边沿,组合四种模式。

  1. SPI 能不能一主多从?

可以,共用三根总线,独立 CS 片选。

  1. SPI 读数据为什么必须发数据?

SPI 时钟由主机提供,没有时钟就不会有移位,不会收到数据,读操作必须靠主机发字节产生时钟。

  1. SPI 溢出错误 OVR 是什么原因?

RX-DR 数据未读取,新数据覆盖旧数据,常见于读取不及时。

  1. SPI 和 I2C 区别?
  • SPI 更快、全双工、无应答、靠片选
  • I2C 较慢、半双工、有应答、靠设备地址

九、总结

  1. SPI 是同步全双工串行总线,核心是双移位寄存器比特互换
  2. 四线架构:SCLK/MOSI/MISO/CS
  3. 四种模式由 CPOL、CPHA 组合,工程默认 Mode0
  4. 内部三大数据单元:TX-DR、RX-DR、移位寄存器
  5. 对外只有 DR 一个数据端口,读写内部自动路由
  6. 读必发、时钟主机说了算、一主多从是常态

十、SPI通信本质建模

结语

如果本篇SPI底层讲解对你有帮助,欢迎点赞👍、收藏⭐,方便以后复习查阅。

内容聚焦嵌入式硬件底层原理,持续更新STM32、通信协议、RTOS、面试相关干货。

欢迎关注+转发给身边一起学嵌入式的小伙伴,一起吃透底层,少走弯路。

有疑问可以评论区留言,一起交流探讨!

相关推荐
别催小唐敲代码1 天前
Pixhawk 6C — Mission Planner 烧录 & 全套校准教程
stm32·单片机·嵌入式硬件
LuminousCPP1 天前
数据结构-二叉树(六):BFS层序遍历与完全二叉树判断|复用链式队列 + (N_0=N_2+1) 性质证明
c语言·数据结构·笔记·算法·二叉树·宽度优先
Brilliantwxx1 天前
【Linux】 进程(10) 进程控制深度解析:创建、终止与等待
linux·运维·服务器·c语言·开发语言·网络
wuyk5551 天前
从零吃透Modbus通信|第7章:终极工程整合(模块化架构、双模式主机从机、RTOS适配、量产级模板)
c语言·stm32·学习·架构
Tim_101 天前
【LeetCode】29、两数相除
算法·leetcode·职场和发展
卢锡荣1 天前
国产PD3.1全集成Type-C管控芯片LDR6020P
c语言·开发语言
Freak嵌入式1 天前
Pico UART 数据收发实战:硬件配置、MicroPython 编程
java·开发语言·单片机·嵌入式硬件·生活
一条破秋裤1 天前
STM32 学习笔记:PWM 驱动 LED 呼吸灯与舵机代码
笔记·stm32·学习
Phil3231 天前
开源一个 Windows 实时面试助手:听译、置顶提词、按需生成英文稿
面试·github
你压到我腿毛了6661 天前
C语言冒泡算法(Bubble sort)
c语言·数据结构·算法