第1章:SPI协议概述——什么是SPI?它的起源与特点

说起SPI,搞嵌入式的人没有不知道的。说白了,它就是一块主芯片和几个外设之间的“传话筒”。我最早接触SPI是十几年前调试一个MCP3204 ADC芯片,那时刚入行,看着示波器上四条信号线来回跳,死活不明白为什么数据会错位。后来才知道,原来是时钟极性和相位没配好——嗯,这坑我至今记忆犹新。

1.1 什么是SPI

SPI 的全名是 Serial Peripheral Interface,串行外设接口。它是个同步串行通信协议,专门用来让微控制器和传感器、存储器、显示屏这类外设交换数据。

你想想看,为什么叫“接口”不叫“总线”?因为 SPI 通常是主从一对一的连接,不需要地址寻址——当然,也可以挂多个从机,靠片选线切换。我个人习惯把 SPI 理解成“四根绳子拉的通信”:时钟线、两根数据线和一根片选线,主设备拉着绳头,从设备跟着节奏走。

1.2 SPI 的起源

SPI 是 Motorola 在上世纪 80 年代推出的,最初用在 MC68HC11 系列单片机里。那时芯片引脚贵啊,Motorola 的设计师想找个比 8 位并行更省引脚、但速度又够快的方案。于是 SPI 诞生了——只占四根线,却能跑到数兆赫兹。后来这个接口被各芯片厂商广泛采纳,成了事实标准。

我记得读一份上世纪的老手册时看到,Motorola 当时还专门写了一份应用笔记,里面画了完整的 SPI 时序图。那时候没有逻辑分析仪,全靠看示波器波形数时钟。现在我们有各种调试工具,但原理还是那些原理。

1.3 SPI 的核心特点

特点说明
全双工发送和接收可以同时进行,不浪费时钟周期
主从架构只有一个主设备主动控制时钟,从设备被动响应
同步所有操作由主设备提供的时钟信号驱动
无应答机制发送方不保证接收方“读到了”,可靠性靠协议上层处理
高速率典型时钟频率可达 10 MHz 以上,远快于 I²C 和 UART

跟 I²C 和 UART 比,SPI 的优势是速度。但缺点也很明显——没有流控,没有确认,多从机时每加一个设备就要多一根片选线。我在一个项目中曾经挂了四个传感器,结果主芯片的 GPIO 被片选占掉好几个,布线时真头疼。

1.4 信号线与连接方式

SPI 用四根信号线:

  • SCLK(串行时钟):由主设备产生,控制数据移位的节奏。
  • MOSI(主出从入):主设备发送数据给从设备。
  • MISO(主入从出):从设备发送数据给主设备。
  • SS(从设备选择,也叫 CS):低电平有效,选中哪个从设备,哪个就工作。

连接方式很简单:主设备的 MOSI 连所有从设备的 MOSI,MISO 同理,SCLK 共享,SS 分别接主设备的 GPIO 引脚。每个从设备独占一根片选线。

// 一个简单的 SPI 初始化示例(基于 STM32 HAL 库)
void MX_SPI1_Init(void)
{
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;   // CPOL = 0
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;       // CPHA = 0
    hspi1.Init.NSS = SPI_NSS_SOFT;
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    HAL_SPI_Init(&hspi1);
}
CPOL 和 CPHA 的四种组合决定了时钟空闲电平以及数据在哪个边沿采样。 这是 SPI 调试中最容易踩坑的地方。我曾经因为 CPOL/CPHA 配错,板子焊好后死活读不到传感器数据,拿逻辑分析仪一看,原来从设备要求时钟空闲为高、数据在第二个边沿采集,而我配反了——唉,一个参数调了整整半天。

小技巧: 我个人的习惯是先用逻辑分析仪抓 CS 信号看有没有正常拉低,再对比手册上的时序图检查极性和相位。如果从设备数据手册里给了时序参数,直接在示波器上测量建立时间(tsu)和保持时间(th)有没有满足。省事又靠谱。

警告——我曾经踩过的坑: 有一次我在 SPI 通信里没有处理好 CS 信号的释放时机。主设备发送完最后一个字节后,CS 立刻拉高,结果从设备内部的移位寄存器还没完成数据锁存,整个通信得重来。后来我加了几个 NOP 的延时,确保最后一个时钟沿之后留够时间再拉高 CS。切记:CS 的释放时序跟 CPHA 配置有直接关系,一定要卡准。

1.5 典型应用场景

  • SD 卡/MMC 卡: 通过 SPI 模式读取文件系统。
  • OLED 显示屏: 很多小屏驱动芯片(如 SSD1306)支持 SPI 接口,速度快于 I²C。
  • 射频模块(RFID、WiFi、BLE): SPI 是芯片间高速数据交换的首选。
  • ADC/DAC: 高精度模数/数模转换器常用 SPI 输出采样值。
  • 存储器(EEPROM、Flash): 几乎所有的 SPI Flash 都是四线制,读写速度达几十 MHz。

你想想看,SPI 之所以用在这么多场景,核心原因就是一个字:快。而且实现简单——主设备给时钟,数据就乖乖移位。但简单不等于容易,调试时常常因为时序细节翻车。

1.6 SPI 协议知识图谱

下面这张图把本章的核心知识串起来了:SPI 的起源、特点、信号线、四种模式和应用场景,画个框架方便你脑子里有个整体印象。

SPI 协议知识结构图 SPI 协议 起源:Motorola 全双工 主从 同步 四根信号线 SCLK MOSI MISO SS/CS CPOL/CPHA 四模式 00 空闲低 上升沿 01 空闲低 下降沿 10 空闲高 下降沿 11 空闲高 上升沿 应用:SD卡 屏 ADC Flash 调试:抓CS 查相位 看建立时间 深色节点内文字白色 连接线使用 #7f8c8d

这张图里,起源、核心特点、四根信号线、时钟相位/极性的四种组合、典型应用和调试要点都画在了一起。你在学习后续章节时随时可以回头看看,想想每个知识点在图上处于哪个分支。

1.7 小结

  • SPI 是同步、全双工、主从串行接口,由 Motorola 在 80 年代提出。
  • 核心四线:SCLK、MOSI、MISO、SS(CS)。
  • CPOL/CPHA 决定时钟空闲电平和采样边沿,四种组合必须配对。
  • 无内置应答机制,上层协议需要自行保证数据完整性。
  • 调试时优先看 CS 时序,再对极性和相位,最后量建立/保持时间。