当前位置: 首页 > backend >正文

【STM32-HAL】 SPI通信与Flash数据写入实战

文章目录

  • 1.参考教程
  • 2. 4种时间模式
  • 3. 3个编程接口
    • 3.1 `HAL_StatusTypeDef HAL_SPI_Transmit(...)` :
      • 3.1.1 参数说明
      • 3.1.2 例子
    • 3.2 `HAL_StatusTypeDef HAL_SPI_Receive(...)` :
      • 3.2.1参数说明
      • 3.2.2 例子
    • 3.3 `HAL_StatusTypeDef HAL_SPI_TransmitReceive(...)` :
      • 3.3.1 参数说明
      • 3.3.2 例子
  • 4. spi应用-flash数据写入
    • 4.1 flash数据写入过程
    • 4.2 流程
    • 5. 流程实现
      • 5.1 写使能
      • 5.2 扇区擦除
      • 5.3 页编程
    • 6. 代码实现
  • 5. spi应用-flash数据加载
    • 5.1 流程
    • 5.2 代码实现

1.参考教程

[STM32 HAL库][SPI]外部flash实验
[STM32 HAL库][SPI]外部flash数据存取

2. 4种时间模式

在这里插入图片描述

3. 3个编程接口

3.1 HAL_StatusTypeDef HAL_SPI_Transmit(...)

用于通过 SPI 总线发送数据,返回 HAL_StatusTypeDef 类型状态值 ,作用为“发送”。

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi,uint8_t *pData,uint16_t Size,uint32_t Timeout)

3.1.1 参数说明

参数名说明
hspi填写 SPI 句柄的指针
pData填写要发送的数据
Size填写要发送的数据的数量,以字节为单位
Timeout超时时间,单位是 ms;HAL_MAX_DELAY 表示无限长的超时时间

3.1.2 例子

在这里插入图片描述

  • 通信场景:主机(单片机)向从机1发送数据 0x5a, 0x33
  • 硬件连接:涉及主机与从机的 MOSI(主机输出从机输入)、MISO(主机输入从机输出 ,从机1此处未动作 )、SCK(时钟 )、NSS(从机选择 ,NSS1 选中从机1 )引脚
  • 代码逻辑
    • 定义发送数据数组 uint8_t dataToSend[] = {0x5a, 0x33};
    • 通过 HAL_GPIO_WritePin 函数拉低引脚选中从机1
    • 调用 HAL_SPI_Transmit 函数发送数据
    • 数据发送后,通过 HAL_GPIO_WritePin 函数拉高引脚取消选中从机1

3.2 HAL_StatusTypeDef HAL_SPI_Receive(...)

用于通过 SPI 总线接收数据,返回 HAL_StatusTypeDef 类型状态值 ,作用为“接收”。

HAL_StatusTypeDef HAL_SPI_Receive(&hspi1, uint8_t *pData, uint16_t Size, uint32_t Timeout)

3.2.1参数说明

参数名说明
参数hspi填写SPI句柄的指针
参数pData填写接收缓冲区
参数Size填写要发送的数据的数量,以字节为单位
参数Timeout超时时间,单位是ms;HAL_MAX_DELAY表示无限长的超时时间

3.2.2 例子

在这里插入图片描述

  1. 功能描述:从从机1接收2个字节的数据
  2. 硬件连接:主机(单片机)与从机1通过MOSI、MISO、SCK、NSS1引脚连接,从机还有从机2、从机3,引脚连接逻辑同从机1
  3. 代码逻辑
    • 定义接收缓冲区 uint8_t dataRcvd[] = {0xff, 0xff};
    • 通过 HAL_GPIO_WritePin(..., GPIO_PIN_RESET); 函数拉低引脚选中从机1
    • 调用 HAL_SPI_Receive(&hspi1, dataRcvd, 2, HAL_MAX_DELAY); 函数,参数含SPI句柄 &hspi1、接收缓冲区 dataRcvd、数据长度 2(字节)、超时时间 HAL_MAX_DELAY(无限超时 )
    • 数据接收后,通过 HAL_GPIO_WritePin(..., GPIO_PIN_SET); 函数拉高引脚取消选中从机1
  4. 时序图:展示NSS1(低电平选中 )、SCK(时钟信号 )、MOSI(发送 0xff0xff 波形 )、MISO(接收 0x1f0x27 波形 )的时序关系 ,呈现SPI接收数据时各信号的变化 。

3.3 HAL_StatusTypeDef HAL_SPI_TransmitReceive(...)

用于通过 SPI 总线同时进行发送和接收数据操作,返回 HAL_StatusTypeDef 类型状态值 ,作用为“发送同时接收”。

HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)

发送数据的同时接收数据

3.3.1 参数说明

参数名说明
参数hspi填写SPI句柄的指针
参数pTxData填写要发送的数据
参数pRxData填写接收数据缓冲区
参数Size发送数据的数量=接收数据的数量,以字节为单位
参数Timeout超时时间,单位是ms

3.3.2 例子

在这里插入图片描述

  1. 功能描述:发送 {0x5a, 0x33} ,同时接收 2 个字节数据
  2. 硬件连接:主机(单片机)与从机 1 通过 MOSI(主机输出从机输入 )、MISO(主机输入从机输出 )、SCK(时钟 )、NSS1(从机选择 )引脚连接,从机还有从机 2、从机 3 ,引脚连接逻辑同从机 1
  3. 代码逻辑
    • 定义发送数据数组 uint8_t txData[] = {0x5a, 0x33};
    • 定义接收缓冲区 uint8_t rxData[2];
    • 通过 HAL_GPIO_WritePin(..., GPIO_PIN_RESET); 函数拉低引脚选中从机 1
    • 调用 HAL_SPI_TransmitReceive(&hspi1, txData, rxData, 2, HAL_MAX_DELAY); 函数,参数含 SPI 句柄 &hspi1、发送数据数组 txData、接收缓冲区 rxData、数据长度 2(字节)、超时时间 HAL_MAX_DELAY(无限超时 )
    • 数据收发后,通过 HAL_GPIO_WritePin(..., GPIO_PIN_SET); 函数拉高引脚取消选中从机 1
  4. 时序图:展示 NSS1(低电平选中 )、SCK(时钟信号 )、MOSI(发送 0x5a0x33 波形 )、MISO(接收 0x1f0x27 波形 )的时序关系 ,呈现 SPI 同时收发数据时各信号的变化 。

4. spi应用-flash数据写入

4.1 flash数据写入过程

在这里插入图片描述

4.2 流程

在这里插入图片描述

5. 流程实现

5.1 写使能

抽水机的写使能是发送0x06
在这里插入图片描述

5.2 扇区擦除

扇区擦除的指令码是0x20,所以首先发送0x20,后面接着24位的扇区首地址

在这里插入图片描述

5.3 页编程

页编程指令码是0x02,后面跟着24位地址(往哪里写地址就发谁的地址),再后面是发要写入的数据,一次性可以写多个数据
在这里插入图片描述

6. 代码实现

static void SaveLEDState(uint8_t ledState)
{// #1. 写使能uint8_t writeEnableCmd[] = {0x06};HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, writeEnableCmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);// #2. 扇区擦除uint8_t sectorErase[] = {0x20, 0x00, 0x00, 0x00};HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, sectorErase, 4, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);HAL_Delay(100);// #3. 写使能HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, writeEnableCmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);// #4. 页编程uint8_t pageProgCmd[5];//要发送5个字节pageProgCmd[0] = 0x02; //页编程指令码是0x02pageProgCmd[1] = 0x00; //地址pageProgCmd[2] = 0x00; //地址pageProgCmd[3] = 0x00; //地址pageProgCmd[4] = ledState; //要发送的数据HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, pageProgCmd, 5, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); HAL_Delay(10); }

在主函数写上 SaveLEDState( ledState);就可以保存灯的状态数据。

5. spi应用-flash数据加载

5.1 流程

读取数据的指令码是0x03,先发0x03,后面跟24位地址,再往后从总线上读取数据。
首先声明数组,用于存放要发送的数据。先发送读取命令,然后接收数据。最后返回读取的数据。
在这里插入图片描述

5.2 代码实现

// 函数:读取LED状态(从Flash等存储设备)
// 功能:通过SPI总线发送读命令,接收并返回存储的LED状态数据
static uint8_t LoadLEDState(void)
{// 读命令及地址:0x03为读数据指令,后三个0x00为起始地址uint8_t readDataCmd[] = {0x03, 0x00, 0x00, 0x00}; uint8_t ledState; // 用于存储读取到的LED状态数据// 选通从设备:拉低GPIOA_PIN_4(SPI从设备片选信号)HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 通过SPI发送读命令:向从设备发送读数据指令及地址,长度4字节,无限超时等待HAL_SPI_Transmit(&hspi1, readDataCmd, 4, HAL_MAX_DELAY); // 通过SPI接收数据:从从设备接收1字节数据(LED状态),存入ledState,无限超时等待HAL_SPI_Receive(&hspi1, &ledState, 1, HAL_MAX_DELAY); // 取消选通:拉高GPIOA_PIN_4,释放从设备片选HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); return ledState; // 返回读取到的LED状态
}
http://www.xdnf.cn/news/16603.html

相关文章:

  • 国产化再进一步,杰和科技推出搭载国产芯片的主板
  • 【CF】Day115——杂题 (构造 | 区间DP | 思维 + 贪心 | 图论 + 博弈论 | 构造 + 位运算 | 贪心 + 构造 | 计数DP)
  • 代码随想录算法训练营第五十五天|图论part5
  • 【音视频】WebRTC-Web 音视频采集与播放
  • 如何利用 Redis 的原子操作(INCR, DECR)实现分布式计数器?
  • CSS-in-JS 动态主题切换与首屏渲染优化
  • IBM Watsonx BI:AI赋能的下一代商业智能平台
  • 领域驱动设计(DDD)在分布式系统中的架构实践
  • jenkins连接docker失败【还是没解决】
  • 基于SpringBoot+MyBatis+MySQL+VUE实现的便利店信息管理系统(附源码+数据库+毕业论文+远程部署)
  • 计算机网络基础(一) --- (网络通信三要素)
  • 【C++算法】77.优先级队列_数据流的中位数
  • PHP云原生架构:容器化、Kubernetes与Serverless实践
  • 机器学习笔记(四)——聚类算法KNN、Kmeans、Dbscan
  • 深入理解 Qt 元对象系统 (Meta-Object System)
  • 架构实战——互联网架构模板(“用户层”和“业务层”技术)
  • 【Linux系统编程】Ext2文件系统
  • 【C++】指针
  • 【面试场景题】阿里云子账号设计
  • 【数据结构】用堆实现排序
  • JavaWeb 入门:JavaScript 基础与实战详解(Java 开发者视角)
  • 「源力觉醒 创作者计划」_文心大模型 4.5 多模态实测:开源加速 AI 普惠落地
  • 某雷限制解除:轻松获取原始下载链接,支持多任务转换
  • Hyperchain安全与隐私机制详解
  • Android Slices:让应用功能在系统级交互中触手可及
  • ElasticSearch 的3种数据迁移方案
  • RabbitMQ 消息持久化的三大支柱 (With Spring Boot)
  • 深度学习篇---百度AI Studio模型
  • JSON-RPC 2.0 规范
  • JVM知识点(2)