文章目录
- 1. STM32 的 SPI 外设简介
- 2. STM32 的 SPI 架构剖析
- 2.1 通讯引脚
- 2.2 时钟控制逻辑
- 2.3 数据控制逻辑
- 2.4 整体控制逻辑
- 3. 通讯过程
- 4. SPI 初始化结构体详解
1. STM32 的 SPI 外设简介
STM32 的 SPI 外设可用作通讯的主机及从机,支持最高的 SCK 时钟频率为 fpclk/2 (STM32F407 型号的芯片默认 fpclk142MHz, fpclk2 为 84MHz),完全支持 SPI 协议的 4 种模式,数据帧长度可设置为 8 位或 16 位,可设置数据 MSB 先行或 LSB 先行。
2. STM32 的 SPI 架构剖析
2.1 通讯引脚
SPI 的所有硬件架构都从图 SPI 架构图 中左侧 MOSI、 MISO、 SCK 及 NSS 线展开的。 STM32 芯片有多个 SPI 外设,它们的 SPI 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚,见表 STM32F4xx 的 SPI 引脚。关于 GPIO 引脚的复用功能,可查阅《STM32F4xx 规格书》,以它为准。
STM32F4xx 的 SPI 引脚
引脚 | SPI 编号 | |||||
---|---|---|---|---|---|---|
SPI1 | SPI2 | SPI3 | SPI4 | SPI5 | SPI6 | |
MOSI | PA7/PB5 | PB15/PC3/PI3 | PB5/PC12/PD6 | PE6/PE14 | PF9/PF11 | PG14 |
MISO | PA6/PB4 | PB14/PC2/PI2 | PB4/PC11 | PE5/PE13 | PF8/PH7 | PG12 |
SCK | PA5/PB3 | PB10/PB13/PD3 | PB3/PC10 | PE2/PE12 | PF7/PH6 | PG13 |
NSS | PA4/PA15 | PB9/PB12/PI0 | PA4/PA15 | PE4/PE11 | PF6/PH5 | PG8 |
其中 SPI1、 SPI4、 SPI5、 SPI6 是 APB2 上的设备,最高通信速率达 42Mbtis/s, SPI2、 SPI3 是 APB1上的设备,最高通信速率为 21Mbits/s。
2.2 时钟控制逻辑
SCK 线的时钟信号,由波特率发生器根据“控制寄存器 CR1”中的 BR[0:2] 位控制,该位是对 fpclk时钟的分频因子,对 fpclk 的分频结果就是 SCK 引脚的输出时钟频率,计算方法见表 BR 位对 fpclk的分频 。
其中的 fpclk 频率是指 SPI 所在的 APB 总线频率, APB1 为 fpclk1, APB2 为 fpckl2。
通过配置“控制寄存器 CR”的“CPOL 位”及“CPHA”位可以把 SPI 设置成前面分析的 4 种 SPI模式。
2.3 数据控制逻辑
SPI 的 MOSI 及 MISO 都连接到数据移位寄存器上,数据移位寄存器的内容来源于接收缓冲区及发送缓冲区以及 MISO、 MOSI 线。
-
当向外发送数据的时候,数据移位寄存器以“发送缓冲区”为数据源,把数据一位一位地通过数据线发送出去;
-
当从外部接收数据的时候,数据移位寄存器把数据线采样到的数据一位一位地存储到“接收缓冲区”中。
通过写 SPI 的“数据寄存器 DR”把数据填充到发送缓冲区中,通过“数据寄存器 DR”,可以获取接收缓冲区中的内容。
2.4 整体控制逻辑
整体控制逻辑负责协调整个 SPI 外设,控制逻辑的工作模式根据我们配置的“控制寄存器(CR1/CR2)”的参数而改变,基本的控制参数包括前面提到的 SPI 模式、波特率、 LSB 先行、主从模式、单双向模式等等。
在外设工作时,控制逻辑会根据外设的工作状态修改“状态寄存器(SR)”,只要读取状态寄存器相关的寄存器位,就可以了解 SPI 的工作状态了。除此之外,控制逻辑还根据要求,负责控制产生 SPI 中断信号、 DMA 请求及控制 NSS 信号线
实际应用中,一般不使用 STM32 SPI 外设的标准 NSS 信号线,而是更简单地使用普通的GPIO,软件控制它的电平输出,从而产生通讯起始和停止信号。
3. 通讯过程
STM32 使用 SPI 外设通讯时,在通讯的不同阶段它会对“状态寄存器 SR”的不同数据位写入参数,通过读取这些寄存器标志来了解通讯状态。
图主发送器通讯过程 中的是“主模式”流程,即 STM32 作为 SPI 通讯的主机端时的数据收发过程
主模式收发流程及事件说明如下:
(1) 控制 NSS 信号线,产生起始信号
(2) 把要发送的数据写入到“数据寄存器 DR”中,该数据会被存储到发送缓冲区;
(3) 通讯开始, SCK 时钟开始运行。 MOSI 把发送缓冲区中的数据一位一位地传输出去; MISO 则把数据一位一位地存储进接收缓冲区中;
(4) 当发送完一帧数据的时候,“状态寄存器 SR”中的“TXE 标志位”会被置 1,表示传输完一帧,发送缓冲区已空;类似地,当接收完一帧数据的时候,“RXNE 标志位”会被置 1,表示传输完一帧,接收缓冲区非空;
(5) 等待到“TXE 标志位”为 1 时,若还要继续发送数据,则再次往“数据寄存器 DR”写入数据即可;等待到“RXNE 标志位”为 1 时,通过读取“数据寄存器 DR”可以获取接收缓冲区中的内容。
假如使能了 TXE 或 RXNE 中断, TXE 或 RXNE 置 1 时会产生 SPI 中断信号,进入同一个中断服务函数,到 SPI 中断服务程序后,可通过检查寄存器位来了解是哪一个事件,再分别进行处理。也可以使用 DMA 方式来收发“数据寄存器 DR”中的数据。
4. SPI 初始化结构体详解
STM32 标准库提供了 SPI 初始化结构体及初始化函数来配置 SPI 外设。初始化结构体及函数定义在库文件“stm32f4xx_spi.h”及“stm32f4xx_spi.c”中
typedef struct
{uint16_t SPI_Direction; /* 设置 SPI 的单双向模式 */uint16_t SPI_Mode; /* 设置 SPI 的主/从机端模式 */uint16_t SPI_DataSize; /* 设置 SPI 的数据帧长度,可选 8/16 位 */uint16_t SPI_CPOL; /* 设置时钟极性 CPOL,可选高/低电平 */uint16_t SPI_CPHA; /* 设置时钟相位,可选奇/偶数边沿采样 */uint16_t SPI_NSS; /* 设置 NSS 引脚由 SPI 硬件控制还是软件控制*/uint16_t SPI_BaudRatePrescaler; /* 设置时钟分频因子, fpclk/分频数 =fSCK */uint16_t SPI_FirstBit; /* 设置 MSB/LSB 先行 */uint16_t SPI_CRCPolynomial; /* 设置 CRC 校验的表达式 */
}SPI_InitTypeDef;