基于个人对STM32的SPI协议的理解

SPI是一种同步串行通信接口,广泛应用于微控制器与外部设备间的数据传输。本文详细介绍了SPI协议的特性,如全双工通信、时钟相位和极性选择,以及从器件选择管理。同时,讲解了SPI在单个主器件/单个从器件应用中的工作原理,包括数据传输的时序和管理。此外,还列举了一系列SPI库函数,用于初始化、配置、发送和接收数据,以及中断和DMA管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

什么是SPI?

SPI协议

IIS特征

SPI 功能说明

SPI 框图​编辑

单个主器件/ 单个从器件应用​编辑

从器件选择 (NSS) 引脚管理

时钟相位和时钟极性

数据时钟时序图​编辑

把 SPI 配置成从器件

发送序列

接收序列

SPI库函数

函数 SPI_DeInit

函数SPI_Init

函数SPI_StructInit

函数SPI_Cmd

函数SPI_ITConfig

函数SPI_DMACmd

函数SPI_SendData

函数SPI_ReceiveData

函数SPI_NSSInternalSoftwareConfig

函数SPI_SSOutputCmd

函数SPI_DataSizeConfig

函数SPI_TransmitCRC

函数SPI_CalculateCRC

函数SPI_GetCRC

函数SPI_GetCRCPolynomial

函数SPI_BiDirectionalLineConfig

函数SPI_GetFlagStatus

函数SPI_ClearFlag

函数SPI_GetITStatus

函数SPI_ClearITPendingBit


什么是SPI?

spi是串行外设接口,SPI是一个同步的数据总线,也就是说它是用单独的数据线一个单独的时钟信号来保证发送端和接收端的完美同步

SPI 接口提供两个主要功能

  • SPI 协议
  • IIS 音频协议

默认情况下,选择的是 SPI 功能。可通过软件将接口从 SPI 切换到IIS。

SPI协议

SPI 特性:

  • 基于三条线的全双工同步传输
  • 基于双线的单工同步传输,其中一条可作为双向数据线
  • 8 位或 16 位传输帧格式选择
  • 主模式或从模式操作
  • 多主模式功能
  • 8 个主模式波特率预分频器(最大值为 f PCLK /2)
  • 从模式频率(最大值为 f PCLK /2)
  • 对于主模式和从模式都可实现更快的通信
  • 对于主模式和从模式都可通过硬件或软件进行 NSS 管理:动态切换主/从操作
  • 可编程的时钟极性和相位
  • 可编程的数据顺序,最先移位 MSB 或 LSB
  • 可触发中断的专用发送和接收标志
  • SPI 总线忙状态标志
  • 具有 DMA 功能的 1 字节发送和接收缓冲器:发送和接收请求

串行外设接口 (SPI) 可与外部器件进行半双工/全双工的同步串行通信。该接口可配置为主模 式,在这种情况下,它可为外部从器件提供通信时钟 (SCK)。该接口还能够在多主模式配置 下工作。 它可用于多种用途,包括基于双线的单工同步传输,其中一条可作为双向数据线,或使用 CRC 校验实现可靠通信

IIS特征

  • 全双工通信
  • 半双工通信(仅作为发送器或接收器)
  • 主模式或从模式操作
  • 8 位可编程线性预分频器,可实现精确的音频采样频率(从 8 kHz 到 192 kHz)
  • 数据格式可以是 16 位、24 位或 32 位
  • 数据包帧由音频通道固定为 16 位(可容纳 16 位数据帧)或 32 位(可容纳 16 位、 24 位、32 位数据帧)
  • 可编程的时钟极性(就绪时的电平状态)
  • 从发送模式下的下溢标志、接收模式下的上溢标志(主模式和从模式),以及接收和发 送模式下的帧错误标志(仅从模式)
  • 发送和接收使用同一个 16 位数据寄存器
  • 用于发送和接收的 DMA 功能(16 位宽)

SPI 功能说明

SPI 框图

 


通常,SPI 通过 4 个引脚与外部器件连接:

  • MISO:主输入/从输出数据。此引脚可用于在从模式下发送数据和在主模式下接收数据。
  • MOSI:主输出/从输入数据。此引脚可用于在主模式下发送数据和在从模式下接收数据。
  • SCK:用于 SPI 主器件的串行时钟输出以及 SPI 从器件的串行时钟输入。
  • NSS:从器件选择。这是用于选择从器件的可选引脚。

单个主器件/ 单个从器件应用

 

注意:此处,NSS 引脚配置为输入

MOSI 引脚连接在一起,MISO 引脚连接在一起。通过这种方式,主器件和从器件之间以串 行方式传输数据(最高有效位在前)

通信始终由主器件发起。当主器件通过 MOSI 引脚向从器件发送数据时,从器件同时通过 MISO 引脚做出响应。这是一个数据输出和数据输入都由同一时钟进行同步的 1 全双工通信 过程。

从器件选择 (NSS) 引脚管理

可以使用 SPI_CR1 寄存器中的 SSM 位设置硬件或软件管理从器件选择。

  • 软件管理 NSS (SSM = 1)

    从器件选择信息在内部由 SPI_CR1 寄存器中的 SSI 位的值驱动。外部 NSS 引脚空 闲,可供其它应用使用。

  • 硬件管理 NSS (SSM = 0) 根据 NSS 输出配置(SPI_CR1 寄存器中的 SSOE 位),硬件管理 NSS 有两种模式。

    • NSS 输出使能(SSM = 0,SSOE = 1) 仅当器件在主模式下工作时才使用此配置。当主器件开始通信时,NSS 信号驱动 为低电平,并保持到 SPI 被关闭为止。
    • NSS 输出禁止(SSM = 0,SSOE = 0) 对于在主模式下工作的器件,此配置允许多主模式功能。对于设置为从模式的器 件,NSS 引脚用作传统 NSS 输入:在 NSS 为低电平时片选该从器件,在 NSS 为 高电平时取消对它的片选。

时钟相位和时钟极性

通过 SPI_CR1 寄存器中的 CPOL 和 CPHA 位,可以用软件选择四种可能的时序关系。 CPOL(时钟极性)位控制不传任何数据时的时钟电平状态。此位对主器件和从 器件都有作 用。如果复位 CPOL,SCK 引脚在空闲状态处于低电平。如果将 CPOL 置 1,SCK 引脚在 空闲状态处于高电平。

如果将 CPHA(时钟相位)位置 1,则 SCK 引脚上的第二个边沿(如果复位 CPOL 位,则 为下降沿;如果将 CPOL 位置 1,则为上升沿)对 MSBit 采样。即,在第二个时钟边沿锁存数据。如果复位 CPHA 位,则 SCK 引脚上的第一个边沿(如果将 CPOL 位置 1,则为下降沿;如果复位 CPOL 位,则为上升沿)对 MSBit 采样。即,在第一个时钟边沿锁存数据。CPOL(时钟极性)和 CPHA(时钟相位)位的组合用于选择数据捕获时钟边沿。

数据时钟时序图

 

所示的时序为 SPI_CR1 寄存器中的 LSBFIRST 位复位时的时序。

把 SPI 配置成从器件

在从模式配置中,从 SCK 引脚上接收主器件的串行时钟。SPI_CR1 寄存器的 BR[2:0] 位中 设置的值不会影响数据传输率。

**注意:**建议在主器件发送时钟前使能 SPI 从器件。否则,数据传输可能会不正常。在主时钟的第一个边沿到来之前或者正在进行的通信结束之前,从器件的数据寄存器就需要准备就绪。在使能从器件和主器件之前,必须将通信时钟的极性设置为空闲时的时钟电平。

发送序列

数据字节在写周期内被并行加载到发送缓冲区中。

当从器件在其 MOSI 引脚上收到时钟信号和数据的最高有效位时,发送序列开始。其余位 (8 位数据帧格式中的 7 个位,16 位数据帧格式中的 15 个位)将加载到移位寄存器中。 SPI_SR 寄存器中的 TXE 标志在数据从发送缓冲区传输到移位寄存器时置 1,并且在 SPI_CR2 寄存器中的 TXEIE 位置 1 时将生成中断。

接收序列

对于接收器,在数据传输完成时

  • 移位寄存器中的数据将传输到接收缓冲区,并且 RXNE 标志(SPI_SR 寄存器)置 1
  • 如果 SPI_CR2 寄存器中的 RXNEIE 位置 1,则生成中断。

在出现最后一个采样时钟边沿后,RXNE 位置 1,移位寄存器中接收的数据字节被拷贝到接 收缓冲区中。当读取 SPI_DR 寄存器时,SPI 外设将返回此缓冲值。

通过读取 SPI_DR 寄存器将 RXNE 位清零。

SPI库函数

 

函数 SPI_DeInit

函数名SPI_DeInit
函数原形void SPI_DeInit(SPI_TypeDef* SPIx)
功能描述将外设 SPIx 寄存器重设为缺省值
输入参数SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输出参数
返回值
先决条件
被调用函数

对 SPI1RCC_APB2PeriphClockCmd().

对 SPI2RCC_APB1PeriphClockCmd().

函数SPI_Init

函数名SPI_Init
函数原形void SPI_DeInit(SPI_TypeDef* SPIx)
功能描述根据 SPI_InitStruct 中指定的参数初始化外设 SPIx 寄存器
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_InitStruct:指向结构 SPI_InitTypeDef 的指针,包含了外设 SPI 的配置信息
输出参数
返回值
先决条件
被调用函数
typedef struct
{
u16 SPI_Direction;   //SPI 方向
u16 SPI_Mode;        //SPI 工作模式
u16 SPI_DataSize;    //SPI 的数据大小
u16 SPI_CPOL;        //选择了串行时钟的稳态
u16 SPI_CPHA;        //设置了位捕获的时钟活动沿
u16 SPI_NSS;         //指定了 NSS 信号由硬件(NSS 管脚)还是软件(使用 SSI 位)管理
u16 SPI_BaudRatePrescaler; //定义波特率预分频的值
u16 SPI_FirstBit;    //指定了数据传输从 MSB 位还是 LSB 位开始
u16 SPI_CRCPolynomial; //定义了用于 CRC 值计算的多项式
} SPI_InitTypeDef; 
  • SPI_Direction SPI_Dirention 设置了 SPI 单向或者双向的数据模式。
  • SPI_Mode 值

  • SPI_DataSize

  • SPI_CPOL

  • SPI_CPHA

 

  • SPI_NSS 值

  • SPI_BaudRatePrescaler 值

**注意:**通讯时钟由主 SPI 的时钟分频而得,不需要设置从 SPI 的时钟。

  • SPI_FirstBit 值

  • SPI_CRCPolynomial

函数SPI_StructInit

函数名SPI_StructInit
函数原形void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
功能描述把 SPI_InitStruct 中的每一个参数按缺省值填入
输入参数SPI_InitStruct:指向结构 SPI_InitTypeDef 的指针,待初始化
输出参数
返回值
先决条件
被调用函数

函数SPI_Cmd

函数名SPI_ Cmd
函数原形void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
功能描述使能或者失能 SPI 外设
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2NewState: 外设 SPIx 的新状态
这个参数可以取:ENABLE 或者 DISABLE
输出参数
返回值
先决条件
被调用函数

函数SPI_ITConfig

函数名SPI_ITConfig
函数原形void SPI_ITConfig(SPI_TypeDef* SPIx, u16 SPI_IT, FunctionalState NewState)
功能描述使能或者失能指定的 SPI 中断
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_IT:待使能或者失能的 SPI 中断源
输入参数 3NewState:SPIx 中断的新状态
输出参数
返回值
先决条件
被调用函数

SPI_IT :输入参数 SPI_IT 使能或者失能 SPI 的中断

函数SPI_DMACmd

函数名SPI_ DMACmd
函数原形void SPI_DMACmd(SPI_TypeDef* SPIx, u16 SPI_DMAReq,FunctionalState NewState)
功能描述使能或者失能指定 SPI 的 DMA 请求
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_DMAReq:待使能或者失能的 SPI DMA 传输请求
输入参数 3NewState:SPIx 中断的新状态
输出参数
返回值
先决条件
被调用函数

SPI_DMAReq :使能或者失能 SPI Tx 和/或 SPI Rx 的 DMA 传输请求

函数SPI_SendData

函数名SPI_ SendData
函数原形void SPI_SendData(SPI_TypeDef* SPIx, u16 Data)
功能描述通过外设 SPIx 发送一个数据
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2Data: 待发送的数据
输出参数
返回值
先决条件
被调用函数

函数SPI_ReceiveData

函数名SPI_ ReceiveData
函数原形u16 SPI_ReceiveData(SPI_TypeDef* SPIx)
功能描述返回通过 SPIx 最近接收的数据
输入参数SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输出参数
返回值接收到的字
先决条件
被调用函数

函数SPI_NSSInternalSoftwareConfig

函数名SPI_NSSInternalSoftwareConfig
函数原形void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, u16 SPI_NSSInternalSoft)
功能描述为选定的 SPI 软件配置内部 NSS 管脚
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_NSSInternalSoft:SPI NSS 内部状态
输出参数
返回值
先决条件
被调用函数

SPI_NSSInternalSoft :内部设置或者重置 NSS 管脚

函数SPI_SSOutputCmd

函数名SPI_SSOutputCmd
函数原形void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState)
功能描述为选定的 SPI 软件配置内部 NSS 管脚
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_NSSInternalSoft:SPI NSS 内部状态
输出参数
返回值
先决条件
被调用函数

函数SPI_DataSizeConfig

函数名SPI_DataSizeConfig
函数原形void SPI_DataSizeConfig(SPI_TypeDef* SPIx, u16 SPI_DatSize)
功能描述设置选定的 SPI 数据大小
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_DataSize:SPI 数据大小
输出参数
返回值
先决条件
被调用函数

函数SPI_TransmitCRC

函数名SPI_ TransmitCRC
函数原形SPI_TransmitCRC(SPI_TypeDef* SPIx, FunctionalState NewState)
功能描述使能或者失能指定 SPI 的 CRC 传输
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2NewState:SPIxCRC 传输的新状态
输出参数
返回值
先决条件
被调用函数

函数SPI_CalculateCRC

函数名SPI_ CalculateCRC
函数原形void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState)
功能描述使能或者失能指定 SPI 的传输字 CRC 值计算
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2NewState:SPIxCRC 传输的新状态
输出参数
返回值
先决条件
被调用函数

函数SPI_GetCRC

函数名SPI_ GetCRC
函数原形u16 SPI_GetCRC(SPI_TypeDef* SPIx)
功能描述返回指定 SPI 的 CRC 值
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_CRC:待读取的 CRC 寄存器
输出参数
返回值CRC 值
先决条件
被调用函数

SPI_CRC :选择 SPI Rx 或者 SPI Tx 的 CRC 寄存器

函数SPI_GetCRCPolynomial

函数名SPI_GetCRCPolynomial
函数原形u16 SPI_GetCRCPolynomial(SPI_TypeDef* SPIx)
功能描述返回指定 SPI 的 CRC 多项式寄存器值
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输出参数
返回值CRC 多项式寄存器值
先决条件
被调用函数

函数SPI_BiDirectionalLineConfig

函数名SPI_BiDirectionalLineConfig
函数原形SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, u16 SPI_Direction)
功能描述选择指定 SPI 在双向模式下的数据传输方向
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_Direction:待读取的 CRC 寄存器
输出参数
返回值CRC 值
先决条件
被调用函数

函数SPI_GetFlagStatus

函数名SPI_ GetFlagStatus
函数原形FlagStatus SPI_GetFlagStatus(SPI_TypeDef* SPIx, u16 SPI_FLAG)
功能描述检查指定的 SPI 标志位设置与否
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_FLAG:待检查的 SPI 标志位
输出参数
返回值SPI_FLAG 的新状态(SET 或者 RESET)
先决条件
被调用函数

函数SPI_ClearFlag

函数名SPI_ ClearFlag
函数原形void SPI_ClearFlag(SPI_TypeDef* SPIx, u16 SPI_FLAG)
功能描述清除 SPIx 的待处理标志位
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_FLAG:待检查的 SPI 标志位
输出参数
返回值SPI_FLAG 的新状态(SET 或者 RESET)
先决条件
被调用函数

函数SPI_GetITStatus

函数名SPI_ GetITStatus
函数原形ITStatus SPI_GetITStatus(SPI_TypeDef* SPIx, u8 SPI_IT)
功能描述检查指定的 SPI 中断发生与否
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_IT:待检查的 SPI 中断源
输出参数
返回值SPI_IT 的新状态
先决条件
被调用函数

函数SPI_ClearITPendingBit

函数名SPI_ ClearITPendingBit
函数原形void SPI_ClearITPendingBit(SPI_TypeDef* SPIx, u8 SPI_IT)
功能描述清除 SPIx 的中断待处理位
输入参数 1SPIx:x 可以是 1 或者 2,来选择 SPI 外设
输入参数 2SPI_IT:待检查的 SPI 中断源
输出参数
返回值SPI_IT 的新状态
先决条件
被调用函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值