SPI总线
- SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口
- 该接口是Motorola 首先提出的全双工三线同步串行外围接口,采用主从模式(Master Slave)架构支持多Slave模式应用,但一般仅支持单Master。

- 时钟由Master控制,在时钟移位脉冲下,数据按位传输,大部分接口,高位在前(MSB first)
- SPI接口有2根单向数据线,为全双工通信,通信双方可同时相互交互数据

- 实际应用中的数据速率可达数10Mbps的水平
- 硬件连线方式:

- MISO:主输入/从输出数据。此引脚可用于在从模式下发送数据和在主模式下接收数据
- MOSI:主输出/从输入数据。此引脚可用于在主模式下发送数据和在从模式下接收数据
- SCK:用于 SPI 主器件的串行时钟输出以及 SPI 从器件的串行时钟输入(主器件负责SCK的输出,从器件只接收)
- CS:从器件选择。这是用于选择从器件的可选引脚。该引脚一般为低电平有效,对于CS为高电平的从器件,不响应SPI总线,可以认为该器件从总线上断开
STM32U575的SPI接口
主要特点
- 三种工作模式:
- 三线全双工同步传输
- 两线半双工同步传输(带双向数据线)
- 两线单工同步传输(带单向数据线)
- 数据大小可选择4位至32位,或固定为8位的倍数
- 支持多主模式或多从模式
- 双时钟域,外设内核时钟独立于APB总线时钟
- 主模式下,波特率预分频器最高可达内核频率/2,或从RCC旁路
- 主从模式下,片选信号(SS)的硬件或软件管理
- 数据之间以及片选信号(SS)与数据流之间可调节的最小延迟
- 可配置的片选信号(SS)极性和时序,具备MISO与MOSI交换功能
- 可编程的时钟极性和相位
- 可编程的数据顺序,支持最高有效位(MSB)优先或最低有效位(LSB)优先移位
- 可编程的单个事务中的数据数量,用于控制片选信号(SS)和循环冗余校验(CRC)
- 具备中断功能的专用发送和接收标志位
- 支持SPI Motorola和TI格式
| 特性 | Motorola SPI 模式 | TI SPI 模式 (SSI) |
|---|---|---|
| 帧格式 | 传统 SPI 帧格式,支持多种时钟极性和相位配置 | 类似 SPI,但帧同步信号(Fss)行为不同 |
| 时钟控制 | 主设备完全控制 SCLK,可配置极性 (CPOL) 和相位 (CPHA) | 时钟极性和相位固定符合 TI 协议要求,用户通常无法配置 |
| 片选信号 (CS) | 低电平有效,通常在整个数据传输期间保持有效(低电平) | 通常在每个数据字传输前产生一个高脉冲(宽度通常为一个时钟周期) |
| 从机 MISO 行为 | 从设备被选中时(CS 有效)MISO 通常可驱动数据线 | 从机仅在数据发送期间驱动 MISO,空闲时保持高阻态 |
| 典型应用 | 大多数标准的 SPI 从设备 | 部分 TI 公司生产的芯片(如某些 ADC、DAC) |
- 硬件CRC功能可在事务结束时验证通信的完整性,具体方式如下:
- 发送(Tx)模式下添加CRC值
- 接收(Rx)模式下自动进行CRC错误检查
- 根据工作模式,在数据溢出、CRC错误、数据不足、模式故障和帧错误情况下,具备中断能力的错误检测功能
- 两个8位倍数的嵌入式接收(Rx)和发送(Tx)先进先出队列(FIFO)(FIFO大小取决于具体接口)
- 可配置的FIFO阈值(数据打包)
- 具备通过系统直接内存访问(DMA)控制器处理数据流的能力
- 片上3个SPI接口特性差异

结构框图


三种通信模式
- 三种模式,通过寄存器 SPI_CFG2 中的COMM[1:0] 位控制
全双工
- COMM[1:0] = 00
- 转换方向的时候,SPI必须无效

半双工
- COMM[1:0] = 11
- 没使用到的SPI数据线可以用作普通的GPIO

单工
- 通过寄存器 SPI_CFG2 中的COMM[1:0] 位控制
- COMM[1:0] = 01,单发送模式
- COMM[1:0] = 10,单接收模式
- 根据通信方向,仅使用一根数据线,另一根没使用到的数据线,可以用作普通的GPIO

一主多从模式

- 同一时刻,主机只能通过GPIO口选中1个从机的片选(SS)进行双向通信
从器件选择(SS)引脚管理
引脚管理涉及的寄存器 SPI_CFG2

- SSOM:主模式下的SS输出管理
- SSOE:SS输出使能
- SSIOP:SS输入/输出极性
- SSM:SS信号输入软件管理
- MSSI[3:0]: 主模式下发出SS有效信号后,在数据发送之前插入的等待时间(以时钟数计)
- MIDI[3:0]:主模式下两帧数据之间插入的等待时间(以时钟数计)


软件SS管理(SSM = 1)
- 从设备模式:从设备选择信息由SPI_CR1寄存器中的SSI位值在内部驱动。外部SS引脚可自由用于其他应用(如作为通用输入输出(GPIO)或其他复用功能)
- 主设备模式:片选信号由软件以控制普通GPIO脚方式进行操作
硬件SS管理(SSM = 0)
SS输出使能(SSOE = 1)
- 仅在微控制器(MCU)设置为主设备时使用
- 当SSOM = 0且SP = 000(Motorola 模式)时,一旦主设备传输开始(CSTART = 1),SS信号即被驱动至有效电平,并保持有效状态,直至其EOT标志被设置或传输被暂停。即使SS引脚未应用SPI复用功能(此时可作为标准GPIO使用),仍需保持SSOE = 1,以确保默认的SS输入电平
- 当SP = 001(TI 模式)时,将按TI模式定义生成一个脉冲
- 当SSOM = 1,SP = 000且MIDI > 1时,在数据帧之间,SS将脉冲至无效状态,并保持无效状态一段时间,该时间长度由MIDI值减一(1至14)后定义的SPI时钟周期数确定。d) 主设备内部强制将SS输入设置为非有效状态,以防止其出现任何模式故障
SS输出禁用(SSOE = 0)
- 如果微控制器在总线上作为主设备运行,此配置允许实现多主设备功能。如果在此模式下SS引脚被拉至有效电平,SPI将进入主设备模式故障状态,且SPI设备将自动重新配置为从模式(MASTER = 0)
- 在从模式下,SS引脚作为标准的"芯片选择"输入,当SS线处于有效电平时,从设备被选中
注意: 当SPI从设备在硬件SS管理模式下启用时,即使发现SS处于有效电平,所有通信也将被忽略。它们将被忽略,直到从设备检测到SS信号的启动(从非有效电平到有效电平的转换),从而使从设备与主设备同步
Ready 引脚(RDY)管理
- 可通过RDY引脚检查从设备处理数据的状态
- 默认情况下,低电平表示从设备未准备好进行数据传输。原因可能是从设备的发送FIFO(TxFIFO)为空、接收FIFO(RxFIFO)已满或SPI(串行外设接口)被禁用
- 信号的有效电平可通过RDIOP位进行选择。如果主设备在从设备显示未就绪状态时继续或开始与之通信,那么传输极有可能失败。
- 当主设备端启用RDY信号输入时,一旦从设备显示未就绪状态,主设备便会暂停通信。这可以防止主设备完成正在进行的一帧传输
- 当主设备不使用RDY时,必须将其禁用(RDIOM = 0)。此时,主设备的内部逻辑会模拟从设备始终处于就绪状态。在这种情况下,RDIOP位的设置无意义
- 由于主从设备两侧时钟域之间的同步以及RDY逻辑的评估,当数据帧大小配置为小于8位时,RDY引脚功能不可靠,无法使用
通信格式
SPI通信过程中的时钟极性和相位
- 通过 SPI_CFG2 寄存器中的 CPOL 和 CPHA 位,可以用软件选择四种可能的时序关系
- CPOL(时钟极性)位控制不传任何数据时的时钟电平状态
- CPOL = 0,SCK 引脚在空闲状态处于低电平
- CPOL = 1,SCK 引脚在空闲状态处于高电平
- CPHA(时钟相位)位控制在第一个还是第二个SCK沿对数据采样
- CPHA = 1,则 SCK 引脚上的第二个边沿对 MSBit 采样。即,在第二个时钟边沿锁存数据
- CPHA = 0,则 SCK 引脚上的第一个边沿对 MSBit 采样。即,在第一个时钟边沿锁存数据
- 四种时序关系产生四种SPI通信模式:
- SPI模式0:CPOL = 0, CPHA = 0
- SPI模式1:CPOL = 0, CPHA = 1
- SPI模式2:CPOL = 1, CPHA = 0
- SPI模式3:CPOL = 1, CPHA = 1

数据帧格式
- SPI移位寄存器可配置为第一位为高位优先(MSB-first)或低位优先(LSB-first)模式。通过SPI_CFG2寄存器中LSBFRST位的值
- 数据帧大小通过SPI_CFG1寄存器的DSIZE[4:0]位进行选择,支持4位至32位的可配置长度,该设置同时适用于发送和接收过程
- 若访问数据量为配置数据大小的整数倍,系统将自动执行数据打包操作。通信过程中,仅数据帧内的有效位会被时钟驱动并传输
SPI初始化配置要点
- SPI使用的时钟源配置
- 使用到的GPIO口初始化为复用功能
- SPI工作模式:Motorola 还是 TI模式?主模式还是从模式?全双工,还是其他?
- SS脚和RDY脚(如果使用)模式配置
- 通信数据宽度配置
- 波特率(时钟预分频系数)配置
- 时钟极性 CPOL 和相位 CPHA 配置
- FIFO阈值
- 如果使用CRC,则配置位数和CRC多项式等
- 如果使用DMA,则配置DMA传输相关内容
SPI数据传输过程控制要点
SPI的启用
- 若SPI配置为从模式,且SS脚使用硬件模式,则需要在非激活状态下,完成配置。即便在配置过程中,SS脚为被选中模式,也不会开始传输,而是需要等待SS脚从非选中状态变化成选中状态。如果SS使用软件模式,没有这种保护机制
- 当SPI被启用,CSTART位被置位,在FIFO不为空时,主设备开始通信
SPI的数据传输和接收
数据帧大小与FIFO阈值
- 一般SPI通信的数据帧为8bit,但也可以设置成其他长度,比如16bit
- SPI接口的FIFO大小都是以8bit为组织形式,为8 * N字节
- SPI接口发送FIFO和接收FIFO是各自独立存在的
- FIFO阈值设置单位是数据帧数,合理设置该值,有助于提升传输效率,减少总线访问次数。阈值设置的帧数,可以看作是一个数据包
- 在数据传输过程中,收到至少1个数据包(接收)或空出至少1个数据包空间(发送)时,分别会触发 RXP和TXP标志,此外,当即发生了RXP又发生了TXP事件,DXP有效。
- 对SPI_RXDR寄存器进行读访问会返回RxFIFO中尚未读取的最旧值。对SPI_TXDR寄存器进行写访问会将写入的数据存储在发送队列末尾的TxFIFO中。(队列先进先出规则)
- 在接收过程中,如果最后收到的数据没有达到阈值,SPI_SR寄存器中的RXWNE和RXPLVL字段会指示FIFO中剩余的接收数据帧数量,但此时应用软件可以仍以之前的方式读取FIFO中的剩余数据,不足一帧数据长度的数据,读出的值为0
- 在发送过程中,最后一个数据的数量可能比配置的数据包大小短,应用程序软件仍可按照用于先前数据填充方式写入FIFO,但此时只有一致的数据会被推入TxFIFO,而冗余的数据会被丢弃
- 数据传输中,可以通过 TXP 和 RXP 触发DMA
主模式下的接收,需要由主机提供CLK信号,为此,需要向总线发送无效数据,需要接收多少数据帧,就需要发生所少数据帧的无效数据
软件控制访问数据寄存器长度的方式为将地址强制类型转换成相应数据长度的指针
事务处理管理
- 用户可以借助存储在寄存器SPI_CR2中TSIZE域的值处理消息中的数据。
- 原则上,当通过设置SPI_CR1寄存器中CSTART位启用SPI时,消息的事务处理开始;当传输所需的数据总数完成时,事务处理结束
- 事务处理的结束控制CRC和硬件从设备选择(SS)管理(如果适用)
- 尽管设置未更改,但强烈建议在下次事务处理开始前禁用并重新启用SPI,以正确重启内部状态机
- 如果设置了FIFO阈值不为1,那么需要设置TSIZE为阈值的整数倍,以保证数据传输的完整性。
- 如果在设置CSTART位时将TSIZE保持为零,则会初始化一个无限事务处理(不应用传输大小控制)。在无限事务处理期间,仅支持与FIFO阈值对齐的传输数据数量。如果数据数量(或其分组到数据包中)不可预测,用户必须将FIFO阈值设置(数据包大小)保持在单个数据(FTHLV =0),以确保每个数据帧都会触发其自己的数据包事件,由应用程序或DMA进行处理
SPI的关闭
- 在主模式下,需要在系统进入低功耗模式且外设时钟停止之前清除SPE位,否则,正在进行的传输可能会遭到破坏
- 在从模式下,当spi_pclk和spi_ker_ck时钟停止时,SPI通信可在无中断的情况下持续进行,直至达到任何通信结束或数据服务请求条件。通常,将系统设置为停止模式(Stop mode)即可停止spi_pclk
- 处于全双工或仅发送模式的主设备在停止提供待传输数据时,可完成任何传输。在此情况下,时钟在最后一次数据传输后停止。可轮询TXC标志(或启用中断,设置EOTIE = 1),以等待最后一帧数据发送完成
- 当主设备处于任何仅接收模式时,为停止外设,必须首先通过将寄存器SPI_CR1中CSUSP位置1来暂停SPI通信。 SPI暂停时,已接收但未读取的数据仍存储在接收FIFO中。 软件暂停后,必须始终禁用SPI,以正确重启内部状态机。
- 禁用SPI时,RxFIFO会被清空。为防止丢失未读数据,用户必须通过读取所有剩余数据(如SPI_SR寄存器中的RXP、RXWNE和RXPLVL字段所示),确保在禁用SPI时RxFIFO为空
- 当主设备通过与SPI无关的GPIO处理SS信号时,必须为从机提供适当的SS脉冲结束信号
SPI通信过程中的CRC校验
- 为确保通信的可靠性,SPI 模块实现了硬件 CRC 功能
- 有两种 CRC 计算标准,具体取决于为发送和/或接收选择的数据帧格式:8 位数据采用 CRC8 ,16位数据采用 CRC16
- 可以通过设置SPI CRC 多项式寄存器 (SPI_CRCPR),实现用户自定义的CRC多项式,如x8+x2+x+1x^8+x^2+x+1x8+x2+x+1 ,则寄存器值可以为0x107
- 在全双工或只发送模式下,非DMA发送方式,在最后传输的数据写入 SPI_DR 后,必须立即对控制寄存器中的 CRCNEXT 位执行写操作。最后一次数据传输结束时,将发送 SPI_TXCRCR 值
- 在只接收模式下,非DMA方式,则在接收到倒数第二个数据后,必须对 CRCNEXT 位执行写操作。在收到最后一个数据后会收到 CRC,然后执行CRC 校验
- 如果传输过程中出现数据损坏,则在数据和 CRC 传输结束时,SPI_SR 寄存器中的 CRCERR标志将置 1
SPI通信过程中的中断
| 中断事件 | 事件标志 | 使能控制位 | 事件清除方法 |
|---|---|---|---|
| TxFIFO 准备好被加载(有空间用于一个数据包 - FIFO 阈值) | TXP | TXPIE | 当 TxFIFO 包含少于 FTHLV 个空位置时,硬件清除 TXP |
| 在 RxFIFO 中接收到数据(有一个数据包可用 - FIFO 阈值) | RXP | RXPIE | 当 RxFIFO 包含少于 FTHLV 个样本时,硬件清除 RXP |
| TXP 和 RXP 都处于活动状态 | DXP | DXPIE | 当 TXP 或 RXP 被清除时 |
| 传输传输已满 | TXTF | TXTIE | 将 TXTFC 写入 1 |
| 欠载 | UDR | UDRIE | 将 UDRC 写入 1 |
| 溢出 | OVR | OVRIE | 将 OVRC 写入 1 |
| CRC 错误 | CRCE | CRCEIE | 将 CRCEC 写入 1 |
| TI 帧格式错误 | TIFRE | TIFREIE | 将 TIFREC 写入 1 |
| 模式故障 | MODF | MODFIE | 将 MODFC 写入 1 |
| 传输结束(基于 TSIZE 值的完整传输序列完成) | EOT | EOTIE | 将 EOTC 写入 1 |
| 主模式暂停 | SUSP | EOTIE | 将 SUSPC 写入 1 |
| TxFIFO 传输完成(TxFIFO 为空) | TXC(3) | EOTIE | 当总线上开始传输活动时,硬件清除 TXC |
SPI的基本应用


c
//阻塞模式数据发送
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi,
const uint8_t *pData,
uint16_t Size,
uint32_t Timeout);
//阻塞模式数据接收
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi,
uint8_t *pData,
uint16_t Size,
uint32_t Timeout);
//阻塞模式数据发送并接收
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi,
const uint8_t *pTxData,
uint8_t *pRxData,
uint16_t Size,
uint32_t Timeout);