16 玩转STM32之SPI通信

简介: 16 玩转STM32之SPI通信

15.1 SPI协议概述


由于时间的原因物理特性之类的这里不在过多的说,如果你是做软件的,这篇是完全没有问题的,因为作为程序开发者,只需要知道他的数据的发送以及时钟特性,其他的并不是很重要,如果你是做硬件开发的话,我认为你只需要参考芯片官方的数据手册就可以了,并不需要你做什么,这方面的电路设计网上也挺多。

SPI是Motorola首先提出的全双工四线同步串行外围接口,采用主从模式(Master-Slave)架构。支持

单主多从模式应用,时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后(MSB first)。

4线SPI器件有四个信号:时钟(SPI CLK, SCLK)、主机输出从机输入(MOSI)、主机输入从机输出(MISO)、片选(CS/NSS)。

为全双工通信,如图是SPI与从机连接示意图:




SPI通信什么时候是主机呢?

产生时钟信号的器件称作主机。主机和从机之间传输的数据与主机产生的时钟同步。

SPI只有一个主机,但是可以有多个从机。

SPI通信示意图:


主机的片选信号用于选择从机,一般是一个低电平有效,拉高时从机与SPI总线断开连接。

MOSI是主机发送从机接収,MISO主机接収从机发送。


15.1.1 SPI数据传输


1、在MOSI、MISO和SPI主从机内部的数据寄存器构成一个数据串行传输的环路,在时钟SCLK的控制下实现数据的环形传输。

要开始SPI通信,主机必须发送时钟信号,并通过使能NSS信号选择从机。

在看一下这个图:


15.1.2 时钟极性和时钟相位


1、CPOL极性(Clock Polarity ,CPOL)

SPI的CPOL,表示当总线空闲时,SCLK的极性,其电平的值是低电平0还是高电平1:

CPOL=0,时钟空闲时候的电平是低电平,所以当SCLK有效的时候,就是高电平;

CPOL=1,时钟空闲时候的电平是高电平,所以当SCLK有效的时候,就是低电平。

2、CPHA相位(Clock Phase ,CPHA)

CPHA相位对应着数据采样是在第一个边沿(空闲态转电平切换到相反电平)还是第二个边沿,

0对应着第一个边沿,1对应着第二个边沿。


15.1.3 四种SPI模式


主机必须根据从机的要求选择时钟极性和时钟相位。

下图是SPI的四种模式:

640.png


下面咱们来说说这几种模式:


1、模式0:

在此模式下,时钟极性CPOL=0,表示时钟信号的空闲状态为低电平。时钟相位CPHA=0,数据在第一个边沿(上升沿)采样,并且数据在时钟信号接下来的下降沿移出。


640.png

2、模式1:


在此模式下,时钟极性CPOL=0,表示时钟信号的空闲状态为低电平。时钟相位CPHA=1,数据在第二个边沿(下降沿)采样,并且数据在时钟信号接下来的上升沿移出。

640.png

3、模式2:

在此模式下,时钟极性CPOL=1,表示时钟信号的空闲状态为高电平。时钟相位CPHA=0,数据在第一个边沿(下降沿)采样,并且数据在时钟信号接下来的上升沿移出。

640.png

4、模式3:


在此模式下,时钟极性CPOL=1,表示时钟信号的空闲状态为高电平。时钟相位CPHA=1,数据在第二个边沿(上升沿)采样,并且数据在时钟信号接下来的下降沿移出。


640.png


15.2 STM32上的SPI


STM32F429内部有6个SPI控制器,可与外部器件进行半双工/全双工的同步串行通信。

SPI控制器主要有以下特性:

全双工同步传输;

8位或 16 位传输帧格式选择;

支持最高的SCK时钟频率为 fpclk/2

主模式或从模式操作、多主模式功能;

可编程的时钟极性和相位;

可编程的数据顺序,先移位 MSB 或 LSB;

可触发中断的专用发送和接收标志;

具有 DMA 功能。

15.2.1 结构

SPI结构图:

STM32 芯片有多个 SPI 外设,它们的 SPI 通讯引脚(MOSI、MISO、SCLK 及 NSS)通过 GPIO 引脚复用映射实现。

SPI引脚图:

6个SPI控制器中SPI1、SPI4、SPI5、SPI6 挂载在 APB2总线上,最高通信速率达45Mbtis/s,SPI2、SPI3挂载在 APB1 总线上,最高通信速率为 22.5Mbits/s。

15.2.2 SPI主机配置

在此配置中,MOSI 引脚为数据输出,MISO 引脚为数据输入。

1、发送数据:在发送缓冲区中写入字节时,SPI控制器开始发送数据。当移位寄存器中的数据都串行输出之后,数据从发送缓冲区传输到移位寄存器,并将TXE 标志置 1,并且在 SPI_CR2寄存器中的 TXEIE 位置 1 时将生成中断。仅当 TXE 标志为 1 时,才可以对发送缓冲区执行写操作。

2、接收数据:对于接收器,在数据传输完成时:移位寄存器中的数据将传输到接收缓冲区,并且 RXNE 标志置 1。如果 SPI_CR2 寄存器中的 RXNEIE 位置 1,则生成中断。在出现最后一个采样时钟边沿时,RXNE 位置 1,移位寄存器中接收的数据字节被拷贝到接收缓冲区中。通过读取 SPI_DR 寄存器获取接收到的数据,并将 RXNE 位清零。


15.2.3 SPI从机配置


在此配置中,从 SCK 引脚上接收主器件的串行时钟。

1、发送数据:数据字节在写周期内被并行加载到发送缓冲区中,当从器件收到时钟信号和数据的高有效位时,开始发送数据。SPI_SR 寄存器中的TXE 标志在数据从发送缓冲区传输到移位寄存器时置 1,并且在SPI_CR2 寄存器中的 TXEIE 位置 1 时将生成中断。

2、接收数据:对于接收器,在数据传输完成时:移位寄存器中的数据将传输到接收缓冲区,并且 RXNE 标志(SPI_SR 寄存器)置 1。如果 SPI_CR2 寄存器中的 RXNEIE 位置 1,则生成中断。通过读取SPI_DR寄存器获取接收到的数据,并将 RXNE 位清零。


15.2.4 主模式的全双工收发过程


通过SPE位置1使能SPI

把第一个数据写入SPI_DR(这种操作会把TXE标志清零)

等到TXE=1,然后写入要发送的第二个数据项。然后等待RXNE=1,读取SPI_DR获取接収第一个数据(RXNE会清零)。然后重复此操作,直到数据接収为止。

等待RXNE=1,读取最后的接収数据

等待TXE=1,然后等待BSY=0,载关闭SPI。




15.2.5 SPI状态标志


软件可通过三种状态标志监视 SPI 总线的状态。

1、发送缓冲区为空 (TXE):此标志置1时,表示发送缓冲区为空,可以将待发送的下一个数据加载到缓冲区中。对SPI_DR 寄存器执行写操作时,将清零 TXE 标志。

2、接收缓冲区非空 (RXNE):此标志置 1 时,表示接收缓冲区中存在有效的已接收数据。读取 SPI_DR 时,将清零该标志。

3、BUSY:BSY 标志由硬件置 1 和清零(对此标志执行写操作没有任何作用)。BSY 标志用于指示SPI 通信的状态。BSY 置 1 时,表示 SPI 正忙于通信。在主模式下的双向通信接收模式(MSTR=1 且 BDM=1且 BDOE=0)有一个例外情况,BSY 标志在接收过程中保持低电平。


15.2.6 SPI中断


15.3 SPI应用步骤及常用库函数


15.3.1 SPI典型应用步骤


以SPI5工作在全双工主模式为例,使用PF6、PF7、PF8、PF9分别作为作为SPI1的NSS、SCLK、MISO和MOSI的复用引脚。


    1、开启SPI5控制器时钟和通信线复用引脚端口GPIOF的时钟。使能SPI5时钟:RCC_APB2PeriphClockCmd (RCC_APB2Periph_SPI5, ENABLE);  使能GPIOA时钟:         RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOA, ENABLE);
    2、初始化引脚复用PF6~PF9到SPI5:  GPIO_PinAFConfig(GPIOF,GPIO_PinSource7,GPIO_AF_SPI5);   GPIO_PinAFConfig(GPIOF,GPIO_PinSource8,GPIO_AF_SPI5);   GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_SPI5);将引脚设置为复用模式,并初始化:  GPIO_Init(GPIOF, &GPIO_InitStructure);
    3、初始化SPI5控制器工作模式。SPI_Init(SPI5, &SPI_InitStructure);
    4、使能SPI5控制器SPI_Cmd(SPI5, ENABLE);
    5、中断使能如果需要使用中断,需要配置NVIC和使能相应的SPI5中断事件。


    15.3.2 常用库函数

    头文件:stm32f4xx_spi.h

    源文件:stm32f4xx_spi.c


      1、SPI初始化函数void   void SPI_Init(SPI_TypeDef*  SPIx, SPI_InitTypeDef*  SPI_InitStruct)1)、参数1:SPI_TypeDef*  SPIx ,SPI应用对象,是一个结构体指针#define SPI1   ((SPI_TypeDef *) SPI1_BASE)2)、参数2:SPI_InitTypeDef*  SPI_InitStruct,是SPI应用对象初始化结构体指针typedef struct{  uint16_t  SPI_Direction;   //定义SPI单向还是双向传输  uint16_t  SPI_Mode;      //定义SPI的主从模式  uint16_t  SPI_DataSize;      //定义SPI传输数据宽度  uint16_t  SPI_CPOL;       // SPI的CPOL极性,定义当SPI空闲时,SCLK的极性  uint16_t  SPI_CPHA;       // SPI的CPHA 相位  uint16_t  SPI_NSS;        //NSS引脚管理方式  uint16_t  SPI_BaudRatePrescaler;   //时钟频率  uint16_t  SPI_FirstBit;        //最先输出的数据位  uint16_t  SPI_CRCPolynomial;  //CRC多项式}SPI_InitTypeDef;SPI_InitTypeDef  SPI_InitStructure;  
      /* FLASH_SPI 模式配置 */// FLASH芯片 支持SPI模式0及模式3,据此设置CPOL CPHASPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主机模式SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//数据位=8bitSPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//SCK 引脚在 空闲状态处于高电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;//SCK第二个边沿采样数据线SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//内部 从器件管理SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//波特率预分频器SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//先发送数据高位SPI_InitStructure.SPI_CRCPolynomial = 7;//SPI_Init(SPI5, &SPI_InitStructure);2、SPI使能函数void  SPI_Cmd(SPI_TypeDef*  SPIx, FunctionalState  NewState);3、SPI发送数据函数void  SPI_I2S_SendData(SPI_TypeDef*  SPIx, uint16_t  Data);4、SPI接收数据函数uint16_t  SPI_I2S_ReceiveData(SPI_TypeDef*  SPIx);5、SPI检测状态标志函数FlagStatus  SPI_I2S_GetFlagStatus(SPI_TypeDef*  SPIx, uint16_t  SPI_I2S_FLAG)


      相关文章
      |
      1月前
      STM32--SPI通信与W25Q64(2)
      STM32--SPI通信与W25Q64(2)
      |
      存储 传感器 芯片
      STM32--SPI通信与W25Q64(1)
      STM32--SPI通信与W25Q64(1)
      |
      9月前
      |
      定位技术
      激光雷达A1M8与STM32通信
      激光雷达A1M8与STM32通信
      124 0
      |
      11月前
      |
      芯片
      15 玩转STM32之IIC通信(芯片硬件篇)(下)
      15 玩转STM32之IIC通信(芯片硬件篇)
      |
      11月前
      |
      芯片
      15 玩转STM32之IIC通信(芯片硬件篇)(上)
      15 玩转STM32之IIC通信(芯片硬件篇)
      |
      11月前
      |
      芯片
      14 STM32之IIC通信(软件模拟篇)
      14 STM32之IIC通信(软件模拟篇)
      |
      IDE 算法 开发工具
      labview与stm32通信
      labview与stm32通信
      156 0
      |
      芯片 异构计算
      STM32 OLED显示屏--SPI通信知识汇总
      在此功能中,采用的是四线SPI,我们在开发过程中,应该去寻扎数据手册里面的通信时序图,才能使得单片机利用四线SPI和OLED进行通信的功能操作。
      STM32 OLED显示屏--SPI通信知识汇总
      |
      数据安全/隐私保护
      STM32的HAL库开发系列 - CAN通信实例
      STM32的HAL库开发系列 - CAN通信实例
      777 0