1st's Studio.

STM32-API

字数统计: 1.7k阅读时长: 6 min
2022/03/03

1.SPI简介

1.1 SPI的通信协议

SPI(Serial Peripheral Interface),顾名思义就是串行外围设备接口,是一种串行同步通讯协议,由一个主设备和一个或多个从设备组成,主设备启动与一个从设备的同步通讯,从而完成数据的交换。

SPI规定了两个SPI设备之间通信必须由主设备(Master)来控制次设备(Slave)。一个Master设备可以通过提供Clock以及对Slave设备进行片选(Slave Select)来控制多个Slave设备,SPI协议还规定Slave设备的Clodck由Master设备通过SCK管教提供给Slave设备,Slave设备本身不能产生或控制Clock,没有Clock则Slave设备不能正常工作

1.2 基本工作原理概述

SPI接口一般由4根线组成,单向传输时3根线也可以。这四根线也是所有基于SPI的设备共有的,它们是SDI(数据输入)、SDO(数据输出)、SCLK(时钟)、CS(片选)。

    1. SDO-主设备数据输出,从设备数据输入;
    1. SDI-主设备数据输入,从设备数据输出;
    1. SCLK-时钟信号,由主设备产生
    1. CS-设备使能信号,由主设备控制

2.SPI特点

2.1.SPI控制方式

SPI采用主-从模式(Master-Slave)的控制方式。

SPI规定了两个SPI设备之间通信必须由主设备(Master)来控制次设备(Slave)。一个Master设备可以通过提供Clock以及对Slave设备进行片选(Slave Select)来控制多个Slave设备,SPI协议还规定Slave设备的Clock由Master设备通过SCK管教提供给Slave设备,Slave设备本身不能产生或控制Clock,没有Clock则Slave设备不能正常工作。

2.2.SPI传输方式

采用同步方式(Synchronous)传输数据

Master设备会根据将要交换的数据来产生相应的时钟脉冲(Clock Pulse),时钟脉冲组成了时钟信号(Clock Signal),时钟信号通过时钟极性(CPOL)和时钟相位(CPHA)控制着两个SPI设备间合适数据交换以及何时对接受到的数据进行采样,来保证数据在两个设备之间是同步传输的。

如上图所示,不论是主机还是从机,在发送数据的同时也接收到了数据。

2.3.SPI数据交换

SPI设备间通信的一个简单概述如下

  • SSPBUF-(Synchronous Serial Port Buffer),泛指SPI设备里面的内部缓冲区,一般在物理上是以FIFO的形式,保存传输过程的临时数据

  • SSPSR-(Synchronous Serail Port Register),泛指SPI设备里面的移位寄存器(Shift Regitser),它的作用是根据设置好的数据位宽(bit-width)把数据移入或者移出SSPBUF

SPI设备间数据传输又被称为数据交换,是因为SPI协议规定一个SPI设备不能在数据通信过程中仅仅只充当一个"发送者或者"接收者(Receiver)"。在每一个Clock周期时间内,SPI都会发送并且同时接受一个bit大小的数据,相当于是这一个bit的数据被交换了,而不是单方面发送。

3.SPI相关代码

首先需要了解SPI的结构体SPI_InitTypeDef的定义

1
2
3
4
5
6
7
8
9
10
11
12
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_Mode用来设置SPI的主从模式,主机模式为SPI_Mode_Master,从机模式为SPI_Mode_Slave
  • SPI_DataSize 为8位还是16位帧格式选择项,SPI_DataSize_8b或者SPI_DataSize_16b
  • SPI_CPOL 用来设置时钟极性。
  • SPI_CPHA用来设置时钟相位,也就是选择在串行同步时钟的第几个跳变沿(上升或下降)数据被采样,可以设置为第一个或者第二个跳变沿采集,SPI_CPHA_1Edge或者SPI_CPHA_2Edge
  • SPI_NSS 设置NSS信号由硬件(NSS管教)还是软件控制。
  • SPI_BaudRatePrescaler是设置SPI波特率预分频值也就是决定SPI的时钟的参数,有8个可选值。
  • SPI_FirstBit设置数据是MSB位在前还是LSB位在前。
  • SPI_CRCPolynomial 是用来设置CRC校验多项式,提高通信可靠性,大于1即可。

在使用SPI之前,需要对SPI进行初始化:

1
2
3
4
5
6
7
8
9
10
11
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex; // 双线双向全双工
SPI_InitStructure.SPI_Mode=SPI_Mode_Master; // 主机模式
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值为7
SPI_Init(SPI2,&SPI_InitStructure); // 根据指定的参数初始化外设SPIx寄存器

在初始化之后,接下来便是使能SPI通信,假设我们使能SPI2,具体的方法是:

1
SPI_Cmd(SPI2,ENABLE);   // 使能SPI外设

接下来便可以使用SPI传输数据,固件库提供的发送函数以及接收函数原型为:

1
2
void SPI_I2S_SendData(SPI_TypeDef* SPIx,uint16_t Data);
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);
第一个函数很好理解,即往SPIx数据寄存器里写入数据Data,从而实现发送。第二个函数就是从SPIx数据寄存器读出接收到的数据

在SPI传输数据过程中,我们经常要判断数据是否传输完成,发送区是否为空等等状态,这是通过函数SPI_I2S_GetFlagStatus实现的:

1
SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE);

利用上述函数,可以封装一个读写的API,即SPIx_ReadWriteByte函数,函数原型为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
u8 SPIx_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESNET)
{
retry++;
if(retry>200) return 0;
}
SPI_I2S_SendData(SPI2,TxData);
retry=0
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESNET)
{
retry++;
if(retry>200) return 0;
}
return SPI_I2S_ReceiveData(SPI2); // 返回通过SPIx最近接收的数据
}

其作用是往SPIx发送缓冲区写入数据的同时可以读取SPIx接收缓冲区中的数据。

那么为什么可以如此实现呢,这需要我们对SPI的框架有所了解。

从框图可以看出SPI有两个缓冲区,一个用于写入(发送缓冲区),一个用于读取(接收缓冲区)。对数据的寄存器执行写操作时,数据将写入发送缓冲区,从数据寄存器执行读取时,将返回接收缓冲区中的值。这样写并不会出现读到的数据等于发送的数据的情况。

参考资料:

[1] STM32 SPI详解

[2] 正点原子STM32F1开发指南(精英版-库函数版)

[3] SPI 读取不同长度 寄存器_STM32硬件SPI主从通信实例

CATALOG
  1. 1. 1.SPI简介
    1. 1.1. 1.1 SPI的通信协议
    2. 1.2. 1.2 基本工作原理概述
  2. 2. 2.SPI特点
    1. 2.1. 2.1.SPI控制方式
    2. 2.2. 2.2.SPI传输方式
    3. 2.3. 2.3.SPI数据交换
  3. 3. 3.SPI相关代码