STM32 SPI实战篇:驱动W25Q64 Flash存储器的技巧与方法

摘要

在嵌入式系统开发中,非易失性存储是必不可少的一部分。W25Q64作为SPI Flash存储器的一种,以其较高的存储密度和擦写次数受到广泛应用。本文将深入探讨STM32通过SPI驱动W25Q64的实战技巧和方法,包括硬件连接、SPI配置、读写操作,以及实际代码示例。

1. SPI通信基础

SPI是一种串行通信协议,其特点包括:

  • 同步通信:数据传输由时钟信号控制。
  • 主从模式:一个主设备控制多个从设备。
  • 全双工:可以同时发送和接收数据。

2. W25Q64 Flash存储器特性

W25Q64是一款8Mbit的SPI Flash存储器,主要特性包括:

  • 容量:8Mbit,相当于1MB。
  • 组织:分为128个扇区,每个扇区包含16页,每页256字节。
  • 接口:SPI。
  • 擦写次数:高达100万次。

3. 硬件连接

W25Q64与STM32的硬件连接如下:

  • CS(片选)连接到STM32 GPIO(如PA4)。
  • SCK(时钟)连接到STM32 SPI时钟引脚(如PA5)。
  • MOSI(数据发送)连接到STM32 SPI数据发送引脚(如PA7)。
  • MISO(数据接收)连接到STM32 SPI数据接收引脚(如PA6)。
  • VCC连接到3.3V。
  • GND连接到地。

4. SPI配置

4.1 SPI初始化

SPI初始化是SPI通信的第一步,需要配置SPI的工作模式、数据大小、时钟极性、时钟相位等。

void SPI_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI1, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);
}

5. W25Q64操作

5.1 W25Q64初始化

W25Q64初始化主要包括SPI初始化和片选信号的配置。

void W25Q64_Init(void) {SPI_Init(); // 初始化SPI// 其他W25Q64特定初始化代码...
}
5.2 读取W25Q64 ID

读取W25Q64的ID是一个简单的操作,可以用来验证设备是否连接正确。

uint16_t W25Q64_ReadID(void) {uint16_t id = 0;SPI_CS_Low(); // 选中W25Q64SPI_SendByte(0x90); // 发送读ID指令id = SPI_ReceiveByte() << 8; // 接收高字节id |= SPI_ReceiveByte(); // 接收低字节SPI_CS_High(); // 取消选中W25Q64return id;
}
5.3 写入W25Q64

写入W25Q64之前,需要先发送写使能指令,然后执行页编程。

void W25Q64_WriteByte(uint32_t addr, uint8_t data) {SPI_CS_Low(); // 选中W25Q64SPI_SendByte(0x06); // 发送写使能指令SPI_SendByte(0x02); // 发送页编程指令SPI_SendByte(addr >> 16); // 发送地址高字节SPI_SendByte(addr >> 8);  // 发送地址中字节SPI_SendByte(addr);       // 发送地址低字节SPI_SendByte(data);       // 发送数据SPI_CS_High(); // 取消选中W25Q64// 等待写入完成...
}
5.4 从W25Q64读取数据

从W25Q64读取数据是一个直接的过程,通过发送读数据指令和地址即可。

uint8_t W25Q64_ReadByte(uint32_t addr) {uint8_t data;SPI_CS_Low(); // 选中W25Q64SPI_SendByte(0x03); // 发送读数据指令SPI_SendByte(addr >> 16); // 发送地址高字节SPI_SendByte(addr >> 8);  // 发送地址中字节SPI_SendByte(addr);       // 发送地址低字节data = SPI_ReceiveByte(); // 接收数据SPI_CS_High(); // 取消选中W25Q64return data;
}

6. 完整示例代码

以下是STM32通过SPI读写W25Q64的完整示例代码。

int main(void) {// 系统初始化SystemInit();// 初始化W25Q64W25Q64_Init();// 读取W25Q64 IDuint16_t id = W25Q64_ReadID();printf("W25Q64 ID: 0x%X\r\n", id);// 测试写入和读取uint32_t testAddr = 0x000000; // 测试地址uint8_t testData = 0xAA;       // 测试数据W25Q64_WriteByte(testAddr, testData); // 写入数据// 延迟一段时间,等待数据写入完成for (volatile int i = 0; i < 0x100000; i++);// 读取数据uint8_t readData = W25Q64_ReadByte(testAddr);if (readData == testData) {printf("Write and Read Test Passed.\r\n");} else {printf("Write and Read Test Failed.\r\n");}while(1) {// 其他应用代码}
}

7. 结论

本文详细介绍了STM32通过SPI接口驱动W25Q64 Flash存储器的实战技巧和方法。通过硬件连接、SPI配置、读写操作的详细步骤和代码示例,读者可以快速掌握SPI通信的实现,并能够应用到自己的项目中。在实际开发中,根据具体的硬件配置和需求进行适当的调整和优化。

✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进

❤欢迎关注我的知乎:对error视而不见

代码获取、问题探讨及文章转载可私信。

☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。

🍎获取更多嵌入式资料可点击链接进群领取,谢谢支持!👇

点击领取更多详细资料

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/36007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

竞赛选题 python+深度学习+opencv实现植物识别算法系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的植物识别算法研究与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;4分 &#x1f9ff; 更多…

基于Java微信小程序自驾游拼团设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f;感兴趣的可以先收藏起来&#xff0c;还…

27. 高级特性(下)

目录 一、为了类型安全和抽象而使用 newtype 模式二、使用类型别名创建类型同义词2.1 使用type关键赋予现有类型一个别名2.2 减少重复2.3 与Result<T, E>结合使用2.4 从不返回的 never type 三、高级函数和闭包3.1 函数指针3.2 返回闭包 四、宏4.1 宏和函数的区别4.2 mac…

python基础语法 003-3 数据类型元组

1 元组 1.1 元组含义 1.1.1 元组的表示 #元组的表示方法:() names ("xiaoyun", "xiaoming") print(names)--结果------- (xiaoyun, xiaoming) 1.1.2 空元组 #空元组 names () print(type(names)) print(len(names))----------------结果--------- &l…

安装vue开发者工具

浏览器控制台提示&#xff1a; 打开网址 GitHub - vuejs/devtools: ⚙️ Browser devtools extension for debugging Vue.js applications. 点击添加 上图地址&#xff1a;Installation | Vue Devtools 安装好了

Spring Boot中如何使用Flyway进行数据库版本控制

Spring Boot中如何使用Flyway进行数据库版本控制 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在现代的软件开发中&#xff0c;数据库版本控制是保证应用程序…

群体优化算法---石墨烯优化算法介绍以及在期权定价上的应用(Black-Scholes模型来计算欧式期权的理论价格)

介绍 石墨烯算法是一种新兴的优化算法&#xff0c;灵感来自于石墨烯的结构和特性。石墨烯是一种由碳原子构成的二维蜂窝状晶格结构&#xff0c;具有优异的机械、电学和热学性能。石墨烯算法通过模拟石墨烯原子之间的相互作用和迁移&#xff0c;来求解复杂的优化问题 基本概念…

K8S -理解StatefulSet - 部署有状态应用

什么是 有状态服务和 无状态服务 有状态服务&#xff08;Stateful Service&#xff09;&#xff1a; 有状态服务是指在处理请求期间维护和跟踪用户状态或会话信息的服务。这意味着服务在多个请求之间保持状态&#xff0c;并且需要在请求之间共享和使用这些状态信息。通常&…

Websocket在Java中的实践——握手拦截器

在《Websocket在Java中的实践——最小可行案例》一文中&#xff0c;我们看到如何用最简单的方式实现Websocket通信。本文中&#xff0c;我们将介绍如何在握手前后进行干涉&#xff0c;以定制一些特殊需求。 在《Websocket在Java中的实践——最小可行案例》的基础上&#xff0c;…

PID原理及控制算法详解

文章目录 1. 概念 1.1 PID框图 1.2 具体示例&#xff1a;无人机高度控制 2. PID原理 3. 常用术语 4. 计算过程 4.1 比例控制&#xff08;Proportional&#xff09; 4.2 积分控制&#xff08;Integral&#xff09; 4.3 微分控制&#xff08;Derivative&#xff09; 5.…

windows@文件高级共享设置@网络发现功能@从资源管理器网络中访问远程桌面

文章目录 高级共享设置常用选项其他选项操作界面说明 网络类型检查和设置(专用网络和公用网络)&#x1f47a;Note 高级共享设置和防火墙&#x1f47a;命令行方式使用图形界面方式配置 网络发现网络发现功能的详细介绍网络发现的作用&#x1f47a;网络发现的工作原理启用和配置网…

SOC和SOH联合估计 | 基于集成ELM的锂离子电池充电截止电压下的SOC和SOH联合估计

目录 研究概述研究内容研究路线研究介绍研究概述 充电截止电压是大多数电动汽车用户充电都会经历的电压点。针对传统安时积分法忽略初始容量误差和电池老化等一系列待优化的问题,提出了双层集成极限学习机(extreme learning machine, ELM)算法,实现锂离子电池充电截止电压下…

【Python实战因果推断】2_因果效应异质性2

目录 CATE with Regression Evaluating CATE Predictions CATE with Regression 我想你可能已经预料到了&#xff1a;与应用因果推理中的大多数情况一样&#xff0c;答案往往从线性回归开始。但在走这条路之前&#xff0c;让我们把事情变得更具体一些。假设你在一家遍布全国的…

[A133]uboot启动流程

[A133]uboot启动流程 hongxi.zhu 2024-6-21 1. 第一阶段 lds描述 从u-boot.lds中能找到程序的汇编入口ENTRY(_start) brandy/brandy-2.0/u-boot-2018/u-boot.lds OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUT…

Spring Boot中的异步编程技巧

Spring Boot中的异步编程技巧 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨在Spring Boot应用程序中如何使用异步编程技巧&#xff0c;以提升性…

LeetCode题练习与总结:单词拆分--139

一、题目描述 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&#xff1a; 输入: s "l…

vant组件 顶部下拉刷新和页面底部下拉获取数据+顶部搜索框

1.html部分&#xff08;顶部tab切换无&#xff0c;只有主体list部分&#xff09; <div class"yd" ><!-- yd端 --><!-- 搜索框 --><van-searchv-model"ydsearchvalue"show-actionplaceholder"请输入搜索关键词"search"…

JavaEE之HTTP协议(1)_HTTP基础知识,HTTP 请求、响应格式,方法,状态码

一、HTTP协议 1.1 基本概念: HTTP全称超文本传输协议&#xff0c;是一种无状态的、应用层的协议&#xff0c;它基于请求/响应模型。客户端&#xff08;通常是Web浏览器&#xff09;通过发送HTTP请求到服务器来获取或发送信息&#xff0c;服务器则返回HTTP响应作为回应。HTTP协…

shell (三)shell脚本

SHELL脚本 编程语言的分类 解释型语言&#xff1a;shell&#xff0c;Python&#xff0c;需要解析器 编译型语言&#xff1a;C语言&#xff0c;C&#xff0c;需要编译器 shell脚本 操作系统的结构 shell&#xff08;贝壳&#xff09; 应用层 app&#xff0c;代码 应用层需要通…

2024年软件测试面试题大全【答案+文档】

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、面试基础题 简述测试流程&#xff1a; 1、阅读相关技术文档&#xff08;如产品PRD、UI设计…