SPI简介


  • SPI工作原理总结

  1. 硬件上为4根线。

  2. 主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。

  3. 串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过MISO信号线返回给主机。这样,两个移位寄存器中的内容就被交换。

  4. 外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

     

     

  • SPI接口简介

    SPI:Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。

    SPI,是一种高速的,全双工同步的通信总线,并且在芯片的管脚上只占用四根线,主要应用在 EEPROMFLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。

    STM32F4 SPI 功能很强大, SPI 时钟最高可以到 37.5Mhz,支持 DMA

     

  • SPI内部结构简明图

    SPI接口一般使用4条线通信:

    MISO 主设备数据输入,从设备数据输出。

    MOSI 主设备数据输出,从设备数据输入。

    SCLK时钟信号,由主设备产生。

    CS从设备片选信号,由主设备控制。

  • SPI接口框图

  • STM32 SPI接口可配置为支持SPI协议或者支持I2S音频协议,默认是SPI模式。可以通过软件切换到I2S方式。 

     

    27.2.1 SPI 特性
    基于三条线的全双工同步传输
    基于双线的单工同步传输,其中一条可作为双向数据线
    8 位或 16 位传输帧格式选择
    主模式或从模式操作
    多主模式功能
    8 个主模式波特率预分频器(最大值为 fPCLK/2
    从模式频率(最大值为 fPCLK/2
    对于主模式和从模式都可实现更快的通信
    对于主模式和从模式都可通过硬件或软件进行 NSS 管理:动态切换主/从操作
    可编程的时钟极性和相位
    可编程的数据顺序,最先移位MSBLSB
    可触发中断的专用发送和接收标志
    SPI 总线忙状态标志
    SPI TI 模式
    用于确保可靠通信的硬件 CRC 功能:
    在发送模式下可将 CRC 值作为最后一个字节发送
    根据收到的最后一个字节自动进行 CRC 错误校验
    可触发中断的主模式故障、上溢和 CRC 错误标志
    具有 DMA 功能的 1字节发送和接收缓冲器:发送和接收请求

     

     

    时钟相位和时钟极性
    通过 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(时钟相位)位的组合用于选择数据捕获时钟边沿。

    数据帧格式
    移出数据时MSB在前还是LSB在前取决于SPI_CR1寄存器中LSBFIRST位的值。每个数据帧的长度均为8位或16位,具体取决于使用SPI_CR1寄存器中的DFF位。所选的数据帧格式适用于发送和/或接收。

     

    从器件选择(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 总线的状态。
    发送缓冲区为空 (TXE)
    此标志置 1 时,表示发送缓冲区为空,可以将待发送的下一个数据加载到缓冲区中。对SPI_DR 寄存器执行写操作时,将清零 TXE 标志。
    接收缓冲区非空 (RXNE)
    此标志置 1 时,表示接收缓冲区中存在有效的已接收数据。读取 SPI_DR 时,将清零该标志。
    BUSY
    BSY标志由硬件置1和清零(对此标志执行写操作没有任何作用)。BSY标志用于指示SPI通信的状态。
    BSY 1 时,表示 SPI 正忙于通信。在主模式下的双向通信接收模式( MSTR=1 BDM=1
    BDOE=0)有一个例外情况, BSY 标志在接收过程中保持低电平。
    如果软件要关闭 SPI 并进入停止模式(或关闭外设时钟),可使用 BSY 标志检测传输是否
    结束以避免破坏最后一个数据的传输。为此,必须严格遵循下述步骤。
    BSY 标志还可用于避免在多主模式系统中发生写冲突。
    传输开始时, BSY 标志将置 1,但在主模式下的双向通信接收模式( MSTR=1 BDM=1
    BDOE=0)下例外。

    在以下情况硬件将清零该标志:
    传输完成时(主模式下的连续通信除外)
    关闭 SPI
    发生主模式故障时 (MODF=1)
    当通信不连续时, BSY 标志在各通信之间处于低电平。
    当通信连续时:
    在主模式下, BSY 标志在所有传输期间均保持高电平
    在从模式下, BSY 标志在各传输之间的一个 SPI 时钟周期内变为低电平
    注意: 请勿使用 BSY标志处理每次数据发送或接收,最好改用 TXE 标志和 RXNE 标志。

     

    SPI 中断



  • 常用寄存器

  • SPI控制寄存器1SPI_CR1)

    SPI控制寄存器1 (SPI_CR1)(不用于I2S模式)SPI control register 1
    偏移地址: 0x00          复位值: 0x0000

7

LSBFIRST 帧格式 (Frame format)
0
:先发送 MSB         1:先发送 LSB
注意: 正在通信时不应更改此位。

不适用于I2S 模式和SPI TI模式

6

SPESPI使能(SPI enable)
0
:关闭外设            1:使能外设
注意: 1- 不适用于 I2S 模式。
注意: 2- 关闭 SPI 时,请按照 27.3.8 节:关闭 SPI中所述的步骤操作。

5:3

BR[2:0] 波特率控制 (Baud rate control)

000: fPCLK/2    100: fPCLK/32

001: fPCLK/4    101: fPCLK/64

010: fPCLK/8    110: fPCLK/128

011: fPCLK/16   111: fPCLK/256

注意: 正在通信时不应更改这些位。

不适用于 I2S 模式

 

  • SPI控制寄存器2SPI_CR2)

  • SPI状态寄存器(SPI_SR)

  • SPI数据寄存器(SPI_DR)

  • SPI_I2S配置寄存器(SPI_I2S_CFGR)

  • SPI_I2S预分频寄存器(SPI_I2SPR)

     

  • SPI相关库函数:

    stm32f4xx_spi.c/stm32f4xx_spi.h

    void SPI_I2S_DeInit(SPI_TypeDef* SPIx);

    void SPI_Init(SPI_TypeDef* SPIx,SPI_InitTypeDef* SPI_InitStruct);

    void SPI_Cmd(SPI_TypeDef* SPIx,FunctionalState NewState);

    void SPI_I2S_ITConfig(SPI_TypeDef* SPIx,uint8_t SPI_I2S_IT, FunctionalState NewState);

    void SPI_I2S_DMACmd(SPI_TypeDef* SPIx,uint16_t SPI_I2S_DMAReq, FunctionalState NewState);

    void SPI_I2S_SendData(SPI_TypeDef* SPIx,uint16_t Data);

    uint16_t SPI_I2S_ReceiveData(SPI_TypeDef*SPIx);

    void SPI_DataSizeConfig(SPI_TypeDef* SPIx,uint16_t SPI_DataSize);

    FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef*SPIx, uint16_t SPI_I2S_FLAG);

    void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx,uint16_t SPI_I2S_FLAG);

    ITStatus SPI_I2S_GetITStatus(SPI_TypeDef*SPIx, uint8_t SPI_I2S_IT);

    void SPI_I2S_ClearITPendingBit(SPI_TypeDef*SPIx, uint8_t SPI_I2S_IT);

     

  • 程序配置过程:

    ①使能SPIxIO口时钟

       RCC_AHBxPeriphClockCmd() / RCC_APBxPeriphClockCmd();

     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);  //使能SPI1时钟

    ②初始化IO口为复用功能

       void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

    ③设置引脚复用映射:

        GPIO_PinAFConfig();

    ②初始化SPIx,设置SPIx工作模式

    voidSPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

    这一步全部是通过SPI1_CR1来设置,我们设置SPI1为主机模式,设置数据格式为8位,然后通过CPOLCPHA位来设置SCK时钟极性及采样方式。并设置SPI1的时钟频率(最大37.5Mhz),以及数据的格式(MSB在前还是LSB在前)。
    SPI_InitTypeDef
    的定义:
    typedef struct
    {

    uint16_t SPI_Direction;
    uint16_t SPI_Mode;
    uint16_t SPI_DataSize;
    uint16_t SPI_CPOL;
    uint16_t SPI_CPHA;
    uint16_t SPI_NSS;
    uint16_t SPI_BaudRatePrescaler;
    uint16_t SPI_FirstBit;
    uint16_t SPI_CRCPolynomial;

    }SPI_InitTypeDef;
    第一个参数SPI_Direction:是用来设置SPI的通信方式,可以选择为半双工,全双工,以及串行
    发和串行收方式,这里我们选择全双工模式SPI_Direction_2Lines_FullDuplex
    第二个参数SPI_Mode:用来设置SPI的主从模式,这里我们设置为主机模式SPI_Mode_Master,当然有需要你也可以选择为从机模式SPI_Mode_Slave
    第三个参数SPI_DataSiz:为8位还是16位帧格式选择项,这里我们是8位传输,选择

    SPI_DataSize_8b
    第四个参数SPI_CPOL:用来设置时钟极性,我们设置串行同步时钟的空闲状态为高电平所以我们选择SPI_CPOL_High
    第五个参数SPI_CPHA:用来设置时钟相位,也就是选择在串行同步时钟的第几个跳变沿(上升或下降)数据被采样,可以为第一个或者第二个条边沿采集,这里我们选择第二个跳变沿,所以选择SPI_CPHA_2Edge
    第六个参数SPI_NSS设置NSS信号由硬件(NSS管脚)还是软件控制,这里我们通过软件控制NSS,而不是硬件自动控制,所以选择SPI_NSS_Soft

    第七个参数SPI_BaudRatePrescaler:很关键,就是设置SPI波特率预分频值也就是决定SPI的时钟的参数,从2分频到256分频8个可选值,初始化的时候我们选择256分频值
    SPI_BaudRatePrescaler_256,
    传输速度为84M/256=328.125KHz
    第八个参数SPI_FirstBit:设置数据传输顺序是MSB位在前还 LSB位在前,这里我们选择

    SPI_FirstBit_MSB高位在前。
    第九个参数SPI_CRCPolynomial:是用来设置CRC校验多项式,提高通信可靠性,大于1即可。
    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //
    双线双向全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //
    SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI
    发送接收 8 位帧结构
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//
    串行同步时钟的空闲状态为高电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//
    第二个跳变沿数据被采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS
    信号由软件控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //
    预分频 256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //
    数据传输从 MSB 位开始
    SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC
    值计算的多项式
    SPI_Init(SPI2, &SPI_InitStructure); //
    根据指定的参数初始化外设 SPIx 寄存器

    ③使能SPIx

        voidSPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

    SPI传输数据

       void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

    uint16_tSPI_I2S_ReceiveData(SPI_TypeDef* SPIx)

    查看SPI传输状态

      SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);

    SPI 初始化函数的最后有一个启动传输,这句话最大的作用就是维持MOSI为高电平,而且这句话也不是必须的,可以去掉。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值