STM32 SPI

Posted 一只小阿大:)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32 SPI相关的知识,希望对你有一定的参考价值。


正点原子STM32 F767 & F429 SPI讲解视频

SPI接口原理

SPI接口简介

SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。

SPI,是一种高速的,全双工同步的通信总线,并且在芯片的管脚上只占用了四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,主要应用在EEPROM,FLASH,实时总线,AD转换器,还有数字信号处理器和数字信号解码器之间。

看见全双工,就起码两根线,才能保证同时能发送接收。
看见同步,就会知道还有一根时钟信号线
那为什么是四根线呢?
还有一根线是片选(连接外设使用)

SPI接口一般使用4条线通信:(可以对着看下面的SPI内部程序框图)
MISO 主设备数据输入,从设备数据输出。(M Master主机 I Input输出 S Slave从机 O Output 输出)
MOSI 主设备数据输出,从设备数据输入。
CSLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。

SPI工作原理总结

  1. 硬件上为4根线。
  2. 主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。
  3. 串行移位寄存器通过MOSI信号线将字节传送给从机,从机也将自己的串行移位寄存器中的内容通过MISO信号线返回给主机。这样,两个移位寄存器中的内容就被交换。
  4. 外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。


STM32 的SPI接口可以配置为支持SPI协议或者支持IIS
音频协议,默认是SPI协议,也可以通过软件方式切换称IIS方式

从设备引脚管理(NSS)

①软件模式:
可以设置SPI_CR1寄存器的SSM位来使能这种模式,在这种模式下NSS引脚可以用作它用,而内部NSS信号电平可以通过写SPI_CR1的SSI位来驱动。

②硬件模式:
第一种情况:NSS输出使能,当STM32工作为SPI模式的时,NSS输出已经通过SPI_CR2寄存器的SSOE位使能,这时NSS引脚被拉低,所有NSS引脚与这个主SPI的NSS引脚相连并配置为硬件NSS的SPI设备,将自动变成从的SPI设备。

第二种情况:NSS输出被关闭:允许操作于多主环境。

时钟信号的相位和极性

SPI_CR寄存器的CPOL和CPHA位,能够组合成四种可能的时序关系,CPOL(时钟极性)位控制在没有数据传输时时钟的空闲状态电平,此位对主模式和从模式下的设备都有效。如果CPOL被清’0’,SCK引脚在空闲状态下保持低电平;如果CPOL被置‘1’,SCK引脚在空闲状态保持高电平。

如果CPHA(时钟相位)位被置‘1’,SCK时钟的第二个边沿(0为下降沿,1为上升沿)进行数据位的采样,数据在第二个时钟边沿被锁存。

如果CPHA位被清0,SCK时钟的第一个边沿(0为下降沿,1为上升沿)进行数据位采集,数据在第一个时钟边沿被锁存。

CPOL时钟极性和CPHA时钟相位的组合选择数据捕捉的时钟边沿。

SPI 接口原理

①数据帧格式
根据SPI_CR1寄存器的LSBFIRST位,输出数据可以选择MSB(高位)先或者LSB(低位)先。
根据SPI_CR1寄存器的DFF位,可以选择数据帧是8位或者16位,对发送和接收都有效。
②状态标志
通过三个标志可以完全监控SPI总线的状态
发送缓存器空闲标志(TXE)
此标志为1的时候,表示发送缓冲寄存器为空,可以写入下一个待发送数据进入缓冲器中,当写入SPI_DR(数据寄存器)时,TXE标志被清除。
接收缓冲器非空(RXNE)
此标志为1表明接收缓冲器中包含有效数据,读SPI数据寄存器可以清楚此标志
忙BUSY标志
BSY标志由硬件设置与清楚,此标志表明SPI通信层的状态

SPI 中断

SPI 引脚配置

SPI 结构体

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; //NSS位
uint16_t SPI_BaudRatePrescaler; uint16_t SPI_FirstBit; //波特率
uint16_t SPI_CRCPolynomial; //CRC校验位
SPI_InitTypeDef;

SPI寄存器库函数配置

①配置引脚,使能时钟
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
②初始化SPI,设置工作模式
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
③使能SPIx
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
④SPI传输数据
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);
⑤查看SPI传输状态
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

编写SPI底层源码

SPI简单理解

因为SPI是全双工加上同步,那么基本上会有四根线,全双工最经典的就是串口,会有个TX还有一个RX,那么SPI全双工是MISO和MOSI,需要同步,那么还需要一个时钟线SCL,还需要一个片选信号线CS,这个CS可以有很多根,也就是说以单片机为主机,可以有多个从机。

三线SPI,这就成单工了,也就是少一个MISO或者少一个MOSI的线

SPI会有四种模式由时钟极性选择(CPOL)和时钟相位选择(CPHA)决定的,分别为SPI(0,1,2,3),其中常用的是0和3

CPOL = 1:表示空闲时是高电平
CPOL = 0:表示空闲时是低电平
CPHA = 0:表示从第一个跳变沿开始采样
CPHA = 1:表示从第二个跳变沿开始采样

以上是关于STM32 SPI的主要内容,如果未能解决你的问题,请参考以下文章

stm32的spi读写只能在一个函数里完成吗?

STM32F103(二十六)SPI通信(+两块STM32之间的SPI通信)

STM32F103(二十六)SPI通信(+两块STM32之间的SPI通信)

STM32 SPI

stm32固件库SPI操作

STM32F103(二十六)SPI通信(+两块STM32之间的SPI通信)