【学习笔记】stm32单片机SPI通信

这几天学完了 stm32 的 SPI 通信，今天来写学习笔记。

（一）什么是 SPI 通信？

SPI（Serial Peripheral Interface）是由 Motorola 公司开发的一种通用数据总线，有四根通信线：SCK（Serial Clock）、MOSI（Master Output Slave Input）、MISO（Master Input Slave Output）、SS（Slave Select，为同步，全双工通信，支持总线挂载多设备（一主多从）。

（二）SPI 硬件电路

SPI 的硬件电路图如下（图片终于能发了！）：

其中 SCK 时钟线与所有设备相连，发送时钟信号；
MOSI 为主机发送从机接收线，MISO 为主机接收从机发送线；
SS 是片选，主机和所有从机都有一条片选来连接，用于指定从机。

（三）SPI 时序

SPI 时序的基本单元为：开始，结束，交换一个字节。
其中与 USART 和 I2C 相比，交换一个字节是 SPI 的一大特征，这个过程就是主机和从机直接进行数据交换，而不是一方发送一方接收。
开始和结束时序比较简单，只需置高或者置低 SS 即可：

交换一个字节由 CPOL 和 CPHA 两个参数决定了四种模式。
CPOL：空闲状态 SCK 电平。
CPHA：SCK 上升沿或下降沿采集数据。
四种模式时序图如下：

（三）软件 SPI

软件 SPI 需要选择四个引脚来配置，其中 SS、SCK、MOSI 配置为推挽输出，MISO 配置为上拉输入：

然后我们写好三个时序基本单元：

随后我们就可以使用这三个时序基本单元组成完整时序使用 SPI 通信了。
这边我们写了 W25Q64 的几个函数，主要是通过命令的方式，先发送开始时序，然后发送命令，然后发送命令的一些参数，最后结束，这里展示读取 ID 的命令：

（四）硬件 SPI

stm32 内部有 SPI 的通信外设，其基本结构如下：

与 I2C 不同，SPI 中发送和接收各有一个缓存区，但共用一个移位寄存器。

配置过程如下：

其中，我们需要把 MOSI 和 SCK 配置为复用推挽输出，其他两个不变（SS 没有用到 SPI 外设，因为 NSS 不具备其功能），然后我们配置结构体，结构体参数如下：
SPI_BaudRatePrescaler—— 波特率，决定传输快慢
SPI_CPHA—— 前面提到的 CPHA
SPI_CPOL—— 前面提到的 CPOL
SPI_CRCPolynomial——CRC 校验，我们这里不需要用到，不过不能置 0，别问我为什么知道。
SPI_DataSize—— 数据大小，我们使用 8 字节传输。
SPI_Direction—— 传输方向，我们选择全双工。
SPI_FirstBit—— 高位先行还是低位先行，我们选择高位先行
SPI_Mode——SPI 模式，我们选择主机模式
SPI_NSS——NSS，用于多主机用的，我们用不到，这里随便选一个。

然后开始和结束时序代码不需要更改，我们改一下交换数据的代码：

代码主要遵照如下时序图：

以上，就是 SPI 的全部内容，886.