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

stm32 W25Q数据存储

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、cubemx配置
  • 二、keil中文件修改与配置
  • 三、几个重要函数的说明
  • 四、DMA方式传输(待写)
  • 总结


前言

W25Q128 容量为128位 128/8 = 16 也就是16M
在这里插入图片描述
在这里插入图片描述
擦除之前必须写使能
在这里插入图片描述
在这里插入图片描述
写数据的存储单元必须是被擦除过的也就是必须是0XFF,不过不是则写入无效。

在这里插入图片描述
此图来源于


一、cubemx配置

全双工SPI
不使用硬件NSS
w25q虽然数据手册写可以达到30mbit/s但是还是建议用10以下的,高了偶尔会出错。

这里参考b站的视频
视频中用的spi3模式,我用的1模式
spi配置
在这里插入图片描述
片选引脚配置
初始化为high 保证上电以后未被片选
在这里插入图片描述

二、keil中文件修改与配置

使用到的代码为b站视频中的链接1 链接2

.h文件这里进行了修改
在这里插入图片描述
在这里插入图片描述
这里注意
前两个 值对任意W25Q都是一样的,不需要修改,4096 也并未用到,目前暂时不修改

//===========Flash存储芯片W25Q128的存储容量参数================
#define		FLASH_PAGE_SIZE			256		//一个Page是256字节
#define		FLASH_SECTOR_SIZE		4096	//一个Sector是4096字节
#define		FLASH_SECTOR_COUNT		4096	//总共4096个 Sector

三、几个重要函数的说明

w25q必须以页为单位来写入,写入前必须要擦除,擦除必须以扇区进行擦除
如果写入前没有擦除,虽然不会报错,但是写入是无效的。
重要函数
Flash_EraseChip();//擦除整个芯片大概20多秒
Flash_EraseBlock64K(globalAddr);//擦除一个块
Flash_EraseSector(memAddress1);//擦除一个扇区 这个是擦除的最单位了
Flash_Addr_byBlockSectorPage(uint8_t BlockNo, uint8_t SubSectorNo, uint8_t SubPageNo) 这个函数是用来得到 块 扇区 页 的那个绝对地址的。

举例
擦除一个扇区

	uint32_t memAddress1 = Flash_Addr_byBlockSectorPage(0, 0, 1);Flash_EraseSector(memAddress1);

向两个页分别写数据

void Flash_TestWrite() {uint8_t BlockNo = 0;uint8_t SubSectorNo = 0;uint8_t SubPageNo = 0;uint32_t memAddress = 0;memAddress = Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);uint8_t bufStr1[30] = "Hello222444";Flash_WriteInPage(memAddress, bufStr1, strlen(bufStr1) + 1);printf("Write in Page0:0\n");printf( "%s",bufStr1);uint8_t bufStr2[30] = "Hello111333";Flash_WriteInPage(memAddress + 100, bufStr2, strlen(bufStr2) + 1);printf( "Write in Page0:100\n");printf( "%s", bufStr2);uint8_t bufPage[FLASH_PAGE_SIZE];for (uint16_t i = 0; i < FLASH_PAGE_SIZE; ++i) {bufPage[i] = 0;}SubPageNo = 1;memAddress = Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);Flash_WriteInPage(memAddress, bufPage, FLASH_PAGE_SIZE);printf("Write 0~255 in Page1");
}

向两个页分别读数据

void Flash_TestRead() {uint8_t BlockNo = 0;uint8_t SubSectorNo = 0;uint8_t SubPageNo = 0;uint32_t memAddress = Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);uint8_t bufStr[50];Flash_ReadBytes(memAddress, bufStr, 50);printf( "Read in Page0:0 ");printf( "%s", bufStr);Flash_ReadBytes(memAddress + 100, bufStr, 50);printf( "Read in Page0:100 ");printf( "%s", bufStr);SubPageNo = 1;memAddress = Flash_Addr_byBlockSectorPage(BlockNo, SubSectorNo, SubPageNo);uint8_t randData12 = Flash_ReadOneByte(memAddress + 12);uint8_t randData136 = Flash_ReadOneByte(memAddress + 136);uint8_t randData210 = Flash_ReadOneByte(memAddress + 210);uint8_t tempStrRandData[30];sprintf(tempStrRandData, "Page1[12]=%d,[136]=%d,[210]=%d",randData12, randData136, randData210);printf( "%s", tempStrRandData);
}

有了 上面两个函数我们就可以做一些小实验了。
第一次使用的时候先对芯片进行整体的擦除
让后调用Flash_TestWrite();函数,此时调用Flash_TestRead() ;函数来读取是正常的
修改代码,不对w25q进行任何擦除直接把Flash_TestWrite();中的bufPage[i] = 0;写成bufPage[i] = i;
这时候读取函数读到的值就是上一次的,说明虽然没有报错,但是并未写入成功
如果对芯片进行该扇区的擦除,再写入即可在读取中获取新的写入。记住写入是按照页来写,擦除是按照扇区擦,一个扇区里面有16个页。

在使用 W25Q 系列的 SPI Flash 存储器时,确实存在写入操作以页为单位(通常为256字节),而擦除操作以扇区为单位(通常为4KB)的限制。这意味着如果你只想修改某个页的数据,而不影响同一扇区内的其他数据,必须采取一些策略来避免丢失扇区中其他页的数据。
解决方法
通常有两种常见的解决方案来应对这个问题:
1扇区读出、修改和写回
步骤:
读出整个扇区:在你需要修改某一页的数据时,先读取整个扇区的数据到内存中。
修改页数据:在内存中修改目标页的数据。
擦除扇区:执行扇区擦除操作。
写回数据:将修改后的数据重新写回该扇区,包括未修改的页数据和修改后的页数据
2使用缓存(缓存区)
步骤
在内存中保留一个缓冲区:该缓冲区的大小等同于一个扇区大小。
管理缓存:每次写入时,先更新缓存区中的数据,然后定期或在缓存区满时写回 SPI Flash。
擦除与写回:当要写入到 Flash 时,执行上述 “扇区读出、修改和写回” 的操作。
优点:可以减少对 Flash 的擦写次数,延长 Flash 的寿命。
总结
无论选择哪种方式,主要思想都是避免直接修改 Flash 中的数据,而是通过在内存中暂存整个扇区的数据,再进行更新和写回操作。这种方式能够有效避免因为写入新数据而导致同一扇区内其他数据的丢失问题。

1扇区读出、修改和写回参考代码

#define SECTOR_SIZE 4096  // W25Q扇区大小
#define PAGE_SIZE 256     // W25Q页大小uint8_t sectorBuffer[SECTOR_SIZE];void updatePageInSector(uint32_t sectorAddr, uint16_t pageOffset, uint8_t* data, uint16_t length) {// 1. 读出整个扇区W25Q_Read(sectorBuffer, sectorAddr, SECTOR_SIZE);// 2. 修改指定页的数据memcpy(&sectorBuffer[pageOffset * PAGE_SIZE], data, length);// 3. 擦除扇区W25Q_EraseSector(sectorAddr);// 4. 将修改后的数据写回整个扇区W25Q_Write(sectorBuffer, sectorAddr, SECTOR_SIZE);
}

注意:W25Q_ReadW25Q_Write 是 SPI Flash 的读写函数;W25Q_EraseSector 是擦除扇区的函数。这里假设你要修改的页在 sectorAddr 的偏移量为 pageOffset 页。

四、DMA方式传输(待写)


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

相关文章:

stm32 W25Q数据存储

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、cubemx配置二、keil中文件修改与配置三、几个重要函数的说明四、DMA方式传输&#xff08;待写&#xff09;总结 前言 W25Q128 容量为128位 128/8 16 也就…...

深度学习的笔记

1. 从huggingface上仅下载pytorch模型权重和配置文件到服务器 import os import shutil from huggingface_hub import snapshot_download# 直接指定模型和下载路径 model_name openai/clip-vit-base-patch32 download_path /home/xxx/.cache/huggingface/hub/models--anas-a…...

音视频入门基础:AAC专题(8)——FFmpeg源码中计算AAC裸流AVStream的time_base的实现

一、引言 本文讲解FFmpeg源码对AAC裸流行解复用&#xff08;解封装&#xff09;时&#xff0c;其AVStream的time_base是怎样被计算出来的。 二、FFmpeg源码中计算AAC裸流AVStream的time_base的实现 FFmpeg对AAC裸流进行解复用&#xff08;解封装&#xff09;时&#xff0c;其…...

React 组件的基本使用,useState 状态变量的使用

React 组件 组件是什么 ##### 概念&#xff1a;一个组件就是用户界面的一部分&#xff0c;它可以有自己的逻辑和外观&#xff0c;组件之间可以相互嵌套&#xff0c;也可以多次复用。 在 React&#xff0c;一个组件就是首字母大写的函数&#xff0c;内部存放了组件的逻辑和视…...

空洞骑士 Hollow Knight 攻略

文章目录 Part.I IntroductionPart.II 攻略Chap.I 地图Chap.II 护符Chap.III BOSSChap.IV 魔法 Reference Part.I Introduction 《空洞骑士》是独立团队 Team Cherry 开发的一款 2D 类银河恶魔城动作冒险游戏。本文记录笔者玩此游戏所积累的一些经验。 「在《空洞骑士》中打造…...

CSP-J 算法基础 广度优先搜索BFS

文章目录 前言广度优先搜索是什么广度优先搜索的实现BFS 的具体编程实现举例&#xff1a;广度优先搜索的具体步骤初始状态&#xff1a;步骤 1&#xff1a;加入起点节点 1步骤 2&#xff1a;访问队列中的节点 1&#xff0c;加入其邻居节点 2 和 4步骤 3&#xff1a;访问队列中的…...

What is new in C# 7,8,9,10

目录 Whats new in C# 7 C# 7 in Visual Studio 2017 Out Variables Pattern Matching Tuples &#xff08;System.ValueTuple&#xff09; Deconstruct解构 Local Functions Ref Returns and Locals Expression Bodied Members Throw Expressions Generated Async R…...

Sqlserver常用sql

1. 数据库和表操作 创建数据库 CREATE DATABASE DatabaseName; 删除数据库 DROP DATABASE DatabaseName; 创建表 CREATE TABLE TableName ( Column1 DataType1, Column2 DataType2, ... ); 删除表 DROP TABLE TableName; 2. 数据操作 插入数据 INSERT INTO TableNam…...

基于SpringBoot+Vue+MySQL的考研互助交流平台

系统展示 用户前台界面 管理员后台界面 系统背景 本文设计并实现了一个基于SpringBoot、Vue.js和MySQL的考研互助交流平台。该平台旨在为广大考研学子提供一个集资源共享、学习交流、经验分享、心理辅导等功能于一体的综合性在线社区。通过SpringBoot构建高效稳定的后端服务&am…...

chatgpt个人版ssrf漏洞

文章目录 免责申明搜索语法漏洞描述漏洞复现修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 搜索语法 fofa title"ChatGPT个人专用版"漏洞描述 该系统是一个开源的…...

如何查看微信聊天记录?四种实用方法查询微信聊天记录,赶快码住!

微信作为我们日常生活中不可或缺的社交工具&#xff0c;记录了大量的聊天内容和重要信息。 当需要查看或恢复微信聊天记录时&#xff0c;很多人可能不知道如何快速、安全地进行操作。 今天&#xff0c;我们就来介绍四种实用的微信聊天记录查询方法&#xff0c;帮助你有效查看微…...

钢材表面缺陷数据集以coco格式做好了数据集的划分,1200张训练集,600张验证集,对应的json文件也在里面

钢材表面缺陷数据集 以coco格式做好了数据集的划分&#xff0c;1200张训练集&#xff0c;600张验证集&#xff0c;对应的json文件也在里面。 钢材表面缺陷检测数据集营销介绍 项目背景&#xff1a; 钢材作为工业生产的重要原材料之一&#xff0c;其表面质量直接影响到成品的性…...

【Lua坑】Lua协程coroutine无法正常完整执行问题

问题&#xff1a;发现Lua协程执行到一半&#xff0c;突然被掐断了一样等到了设定的时间没有正常执行协程后续代码&#xff01;非必现bug&#xff0c;若发生大概率在高频率使用协程时易触发。 LuaFramework或xLua uLua都自带有协程coroutine&#xff0c;而且基本都使用对象池缓…...

istio中serviceentry结合egressgateway的使用

假设有一个外部服务&#xff0c;外部服务ip为&#xff1a;10.10.102.90&#xff0c;其中32033为v1版本&#xff0c;32034为v2版本。 现在需要把这个服务引入到istio中&#xff0c;并且需要配置所有访问该服务的流量都通过egressgateway转发出去。 serviceentry apiVersion: n…...

使用 Python 实现 Windows 应用图标的便捷生成:一站式 PNG 转 ICO 工具20240918

使用 Python 实现 Windows 应用图标的便捷生成&#xff1a;一站式 PNG 转 ICO 工具 在开发 Windows 桌面应用程序时&#xff0c;图标文件&#xff08;ICO&#xff09;的生成是不可忽视的关键步骤。无论是任务栏图标、快捷方式&#xff0c;还是应用程序的主图标&#xff0c;都需…...

编程环境常用命令合集

cmd: python 进入python运行环境 exit()/quit()/ctrlZ 退出环境 rmdir /s venv 删除环境 pip命令&#xff1a; pip list 查看所有库 pip install <库> 安装库 -i <数据源>可指定安装数据源 pip install <库>x.x.x 安装指定版本的库 pip install --upgrade &…...

Qt Creator 集成开发环境 常见问题

1.QtCreator中三种不同编译版本 debug、release、profile 的区别 在 Qt Creator 中&#xff0c;Debug、Release 和 Profile 是三种不同的构建配置&#xff0c;它们主要用于在开发过程中生成不同类型的可执行文件。它们的区别如下&#xff1a; 1.1 Debug&#xff08;调试版本&…...

使用Faiss进行K-Means聚类

&#x1f4dd; 本文需要的前置知识&#xff1a;Faiss的基本使用 目录 1. 源码剖析1.1 参数解释 2. 聚类过程详解2.1 初始化聚类中心2.2 分配步骤&#xff08;Assignment&#xff09;2.3 更新步骤&#xff08;Update&#xff09;2.4 收敛与终止条件 3. GPU 加速3.1 索引结构与 G…...

通过hosts.allow和hosts.deny限制用户登录

1、Hosts.allow和host.deny说明 两个文件是控制远程访问设置的&#xff0c;通过设置这个文件可以允许或者拒绝某个ip或者ip段的客户访问linux的某项服务。如果请求访问的主机名或IP不包含在/etc/hosts.allow中&#xff0c;那么tcpd进程就检查/etc/hosts.deny。看请求访问的主机…...

PWN College 关于sql盲注

在这个场景中&#xff0c;我们需要利用SQL注入漏洞来泄露flag&#xff0c;但是应用程序并不会直接返回查询结果。相反&#xff0c;我们需要根据应用程序的行为差异&#xff08;登录成功与否&#xff09;来推断查询结果。这就是所谓的"布尔盲注"&#xff08;Boolean-b…...

【Linux篇】Http协议(1)(笔记)

目录 一、http基本认识 1. Web客户端和服务器 2. 资源 3. URI 4. URL 5. 事务 6. 方法 7. 状态码 二、HTTP报文 1. 报文的流动 &#xff08;1&#xff09;流入源端服务器 &#xff08;2&#xff09;向下游流动 2. 报文语法 三、TCP连接 1. TCP传输方式 2. TCP连…...

员工疯狂打CALL!解锁企业微信新玩法,2024年必学秘籍来啦!

现在工作离不开电脑手机&#xff0c;公司交流也得用新招。腾讯出了个企业微信&#xff0c;就是给公司用的聊天工具。它功能强大&#xff0c;操作简便&#xff0c;很多公司用它来让工作更高效&#xff0c;团队合作更紧密。接下来&#xff0c;我会简单说说怎么上手企业微信&#…...

Spring boot从0到1 - day01

前言 Spring 框架作为 Java 领域中最受欢迎的开发框架之一&#xff0c;提供了强大的支持来帮助开发者构建高性能、可维护的 Web 应用。 学习目标 Spring 基础 Spring框架是什么&#xff1f;Spring IoC与Aop怎么理解&#xff1f; Spring Boot 的快速构建 Spring 基础 学习…...

Flutter 项目结构的区别

如果需要调用原生代码&#xff0c;请创建一个plugin类型的项目开发。如果需要调用C语言&#xff0c;请参考文档&#xff1a;Flutter项目中调用C语言plugin 其实是 package 的一种&#xff0c;全称是 plugin package&#xff0c;我们简称为 plugin&#xff0c;中文叫插件。 1. A…...

EfficientFormerV2:重新思考视觉变换器以实现与MobileNet相当的尺寸和速度。

摘要 https://arxiv.org/pdf/2212.08059 随着视觉变换器&#xff08;ViTs&#xff09;在计算机视觉任务中的成功&#xff0c;近期的研究尝试优化ViTs的性能和复杂度&#xff0c;以实现在移动设备上的高效部署。提出了多种方法来加速注意力机制&#xff0c;改进低效设计&#xf…...

ASP.NET Core高效管理字符串集合

我们在开发 Web 项目时经常遇到需要管理各种来源的字符串集合&#xff08;例如HTTP 标头、查询字符串、设置的值等&#xff09;的情况。合理的管理这些字符串集合不仅可以减少出bug的几率&#xff0c;也能提高应用程序的性能。ASP.NET Core 为我们提供了一种特殊的只读结构体 S…...

vm-tools的卸载重装,只能复制粘贴,无法拖拽文件!

开始 ubuntu22.04 LTSVMwareTools-10.3.25-20206839.tar.gzVMware Workstation 17 Pro 各种该尝试的配置都尝试了,比如: 1.开启复制粘贴拖拽; 2.VMware Tools拖拽失效; 3.解决VMware无法拖拽. 均没有奏效. 安装过程报错, 报错异常: The installation of VMware Tools 10.3.25…...

Docker 容器网络技术

Docker 容器网络技术 一、概述 Docker 容器技术在微服务架构和云原生应用中扮演着重要角色。容器的轻量化和快速启动特性&#xff0c;使得它们成为现代应用部署的首选。然而&#xff0c;容器的网络连接和管理是一个复杂的问题&#xff0c;尤其是当涉及到容器间通信时。Docker…...

C++ 起始帧数、结束帧数、剪辑视频

C 指定起始帧数、结束帧数、 剪辑视频 C 无法直接用H264&#xff0c;只能用avi编码格式 #include <iostream> #include <opencv2/opencv.hpp>int main() {// 读取视频&#xff1a;创建了一个VideoCapture对象&#xff0c;参数为摄像头编号std::string path &quo…...

【项目一】基于pytest的自动化测试框架———解读requests模块

解读python的requests模块 什么是requests模块基础用法GET与POST的区别数据传递格式会话管理与持久性连接处理相应结果应对HTTPS证书验证错误处理与异常捕获 这篇blog主要聚焦如何使用 Python 中的 requests 模块来实现接口自动化测试。下面我介绍一下 requests 的常用方法、数…...