【STM32】SPI协议整理:硬件连接、通信时序与HAL库操作
文章目录
- 【STM32】SPI协议整理:硬件连接、通信时序与HAL库操作
- 概述
- 一、SPI程序层次
- 1.1 SPI硬件原理图解析
- 1.2 硬件框图 & 软件层次
- 二、SPI 协议
- 2.1 CS 片选
- 2.2 SPI 是怎么传 1 字节数据
- 2.3 SPI模式
- 三、HAL 编程
- 3.1 STM32CubeMX 配置
- 3.2 查询方式函数说明
- 3.3 中断方式函数说明
- 3.4 DMA 方式函数说明
- 3.5 W25Q64 操作方法
概述
SPI 可以理解为:主控 MCU 按自己给出的时钟节拍,和外设一边发数据、一边收数据的高速串行通信协议。(同步)(全双工)
SPI 接口主要应用在 EEPROM、 FLASH、实时时钟、网络控制器、 OLED 显示驱动器、 AD转换器,数字信号处理器、数字信号解码器等设备之间。
一、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_StatusTypeDefHAL_SPI_TransmitReceive(SPI_HandleTypeDef*hspi,uint8_t*pTxData,uint8_t*pRxData,uint16_tSize,uint32_tTimeout);/* 发送数据 */HAL_StatusTypeDefHAL_SPI_Transmit(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize,uint32_tTimeout);/* 接收数据 */HAL_StatusTypeDefHAL_SPI_Receive(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize,uint32_tTimeout);| 参数 | 说明 |
|---|---|
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_StatusTypeDefHAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef*hspi,uint8_t*pTxData,uint8_t*pRxData,uint16_tSize);/* 发送数据 */HAL_StatusTypeDefHAL_SPI_Transmit_IT(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize);/* 接收数据 */HAL_StatusTypeDefHAL_SPI_Receive_IT(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize)/* 发送、接收完成回调函数 */voidHAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef*hspi);/* 发送完成回调函数 */voidHAL_SPI_TxCpltCallback(SPI_HandleTypeDef*hspi);/* 接收完成回调函数 */voidHAL_SPI_RxCpltCallback(SPI_HandleTypeDef*hspi)/* 出错回调函数 */voidHAL_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_StatusTypeDefHAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef*hspi,uint8_t*pTxData,uint8_t*pRxData,uint16_tSize);/* 发送数据 */HAL_StatusTypeDefHAL_SPI_Transmit_DMA(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize);/* 接收数据 */HAL_StatusTypeDefHAL_SPI_Receive_DMA(SPI_HandleTypeDef*hspi,uint8_t*pData,uint16_tSize);/* 发送、接收完成回调函数 */voidHAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef*hspi);/* 发送完成回调函数 */voidHAL_SPI_TxCpltCallback(SPI_HandleTypeDef*hspi);/* 接收完成回调函数 */voidHAL_SPI_RxCpltCallback(SPI_HandleTypeDef*hspi)/* 出错回调函数 */voidHAL_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芯片手册
欢迎大家一起交流讨论!