【STM32】SPI协议整理:硬件连接、通信时序与HAL库操作
文章目录
- 【STM32】SPI协议整理:硬件连接、通信时序与HAL库操作
-
- 概述
- 一、SPI程序层次
-
- [1.1 SPI硬件原理图解析](#1.1 SPI硬件原理图解析)
- [1.2 硬件框图 & 软件层次](#1.2 硬件框图 & 软件层次)
- [二、SPI 协议](#二、SPI 协议)
-
- [2.1 CS 片选](#2.1 CS 片选)
- [2.2 SPI 是怎么传 1 字节数据](#2.2 SPI 是怎么传 1 字节数据)
- [2.3 SPI模式](#2.3 SPI模式)
- [三、HAL 编程](#三、HAL 编程)
-
- [3.1 STM32CubeMX 配置](#3.1 STM32CubeMX 配置)
- [3.2 查询方式函数说明](#3.2 查询方式函数说明)
- [3.3 中断方式函数说明](#3.3 中断方式函数说明)
- [3.4 DMA 方式函数说明](#3.4 DMA 方式函数说明)
- [3.5 W25Q64 操作方法](#3.5 W25Q64 操作方法)
概述
一、SPI程序层次
1.1 SPI硬件原理图解析
| SPI_Flash模块 |
SPI硬件原理图 |
 |
 |
| MCU 引脚 |
SPI 名称 |
Flash 引脚 |
作用 |
| PA7 |
MOSI |
DI |
MCU ==> Flash |
| PA6 |
MISO |
DO |
Flash ==> MCU |
| PA5 |
SCK |
SCK |
MCU 提供时钟(节拍) |
| PB9 |
CS |
CS |
片选,选择某个 Flash |
| GND |
GND |
GND |
共地 |
| VCC |
VCC |
VCC |
供电 |
1.2 硬件框图 & 软件层次
| SPI 硬件框图 |
SPI 软件层次 |
 |
 |
程序 ==>通过SPI控制器 来操作SPI Flash(SPI设备)
二、SPI 协议
2.1 CS 片选
| 硬件连线 |
 |
|
- SPI设备只能片选一个,谁的 CS 被拉低,谁就被选中
2.2 SPI 是怎么传 1 字节数据
| SPI 传输一个字节 |
 |
|
 |
2.3 SPI模式
| SPI 模式 |
CPOL |
CPHA |
| Mode 0 |
0(SCK初始电平为低) |
0(在第一个时钟沿采样数据) |
| Mode 1 |
0(SCK初始电平为低) |
1(在第二个时钟沿采样数据) |
| Mode 2 |
1(SCK初始电平为高) |
0(在第一个时钟沿采样数据) |
| Mode 3 |
1(SCK初始电平为高) |
1(在第二个时钟沿采样数据) |
- 不管是什么模式,SPI协议 都可以同时发送八位数据,同时接收到八位数据 (交换数据)
三、HAL 编程
3.1 STM32CubeMX 配置
| 配置 SPI |
配置 CS 片选 |
 |
 |
3.2 查询方式函数说明
/* 发送同时接收数据 */
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);
/* 发送数据 */
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
/* 接收数据 */
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);
| 参数 |
说明 |
SPI_HandleTypeDef *hspi |
使用哪个 SPI 控制器 |
uint8_t *pTxData或uint8_t *pData |
要发送的数据的 buffer |
uint8_t *pRxData或uint8_t *pData |
存储接收到的数据是 buffer |
uint16_t Size |
数据个数 |
uint32_t Timeout |
超时时间,单位是 Tick,一般是 1ms |
| 返回值 |
HAL_OK:成功HAL_ERROR:错误HAL_BUSY:总线忙HAL_TIMEOUT:超时 |
3.3 中断方式函数说明
| STM32cubeMX 配置中断方式 |
 |
|
/* 发送同时接收数据 */
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);
/* 发送数据 */
HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_tSize);
/* 接收数据 */
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
/* 发送、接收完成回调函数 */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
/* 发送完成回调函数 */
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
/* 接收完成回调函数 */
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
/* 出错回调函数 */
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
| 参数 |
说明 |
SPI_HandleTypeDef *hspi |
使用哪个 SPI 控制器 |
uint8_t *pTxData / uint8_t *pData |
要发送的数据的 buffer |
uint8_t *pRxData / uint8_t *pData |
存储接收到的数据是 buffer |
uint16_t Size |
数据个数 |
uint32_t Timeout |
超时时间,单位是 Tick,一般是 1ms |
| 返回值 |
HAL_OK:成功 HAL_ERROR:错误 HAL_BUSY:总线忙 HAL_TIMEOUT:超时 |
3.4 DMA 方式函数说明
| STM32cubeMX 配置DMA方式 |
 |
|
/* 发送同时接收数据 */
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);
/* 发送数据 */
HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
/* 接收数据 */
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);
/* 发送、接收完成回调函数 */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
/* 发送完成回调函数 */
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
/* 接收完成回调函数 */
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
/* 出错回调函数 */
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
| 参数 |
说明 |
SPI_HandleTypeDef *hi2c |
使用哪个 I2C 控制器 |
uint16_t DevAddress |
设备地址,需要把 7 位地址左移 1 位 |
uint8_t *pData |
数据 buffer |
uint16_t Size |
数据个数 |
| 返回值 |
HAL_OK:成功HAL_BUSY:总线忙 |
3.5 W25Q64 操作方法
| 读数据 |
 |
|
- 写使能、读状态,擦除扇区,烧写页 见W25Q64芯片手册
欢迎大家一起交流讨论!