W25Q64讲解及历程

news2024/11/16 21:35:16

W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器(ROM)

ROM的特点就是掉电不丢失也就是非易失性存储器,和RAM掉电丢失不同;

常应用于数据存储、字库存储、固件程序存储等场景;

存储介质:Nor Flash(闪存)

时钟频率:80MHz / 160MHz (Dual SPI双重SPI) / 320MHz (Quad SPI四重SPI);

Dual SPI双重SPI:也就是和普通的比多了两根MISO和MOSI,在一个时钟内传两位,但是实际上每一根还是传一位,本质上没有改变。

四重以此类推。

存储容量(24位地址)也是就对应0X000000      

简单介绍以下W25Q64的区域划分:

我们对于数据的管理存储结构:W25Q64通常以块(Block)、扇区(Sector)和页(Page)的形式组织存储数据。W25Q64一共有128块,每个块包含16个扇区,每个扇区包含16个页,每页最多256字节。

举例而言一个省当中有128个学校,每个学校有16个校区,每个校区有16个院系,每个院系最多有256个学生。

实际内存就是256byte✖16✖16✖128=8388608(Byte)=8192KB=8MB

也就是对应的0X000000~0X7FFFFF的内存大小,同时也代表了我们使用时候的寻址空间大小。

这边列举以下W25QXX系列的存储大小:

型号内存大小
W25Q404Mbit / 512KByte   
W25Q808Mbit / 1MByte   
W25Q1616Mbit / 2MByte     
W25Q3232Mbit / 4MByte   
W25Q64   64Mbit / 8MByte     
W25Q128128Mbit / 16MByte   
 W25Q256256Mbit / 32MByte

实际使用时候我们需要根据要存入数据大小,一般是数据包,字符库等等大小选择外挂的ROM

我们在写入数据的时候需要按照下面的指令集发送指令:

指令集1:

我们知道SPI通信的模型其实是一种交换数据,我们要求执行某项命令,首先要发送指令,然后按照我们指令集当中表格完成时序,表格当中对应的后续字节的表格完成时序图。

其中dummy代表就是我们用户可以随便发送数据,因为我们假设发送指令后,同样的从机也会发送数据给我们交换数据,而从机接收指令后往往有的时候会发多个我们需要的数据,但是由于SPI交换数据的模型我们需要拿没有用处的数据去交换,所以这种数据就是无意义的dummy:假的。

其中括号“()”的字节字段,手册当中给出:

1. Data bytes are shifted with Most Significant Bit first. Byte fields with data in parenthesis “()” indicate data being read from the device on the DO pin. 表示从DO引脚上的设备读取的数据。

我们实际使用过程往往不一定是读取的也有可能写入的比如我们Page Program:页面程序当中我们最后的(D7–D0) 代表我们需要写入存储页的数据。

我们对于使用Flash写入操作的时候需要注意的地方非常多,指令集1大多为写入操作

注意:

1.我们进行写入操作前,必须先进行写使能(Write Enable 对应指令06h)

类似于我们进入房子需要开门解锁才能进去访问这样,flash访问也需要使能,在STM32当中也说解锁。

2.写入数据前必须先擦除,擦除后,所有数据位变为1。

这个是由于我们Flash不擦除的话,每个数据位只能由1改写为0,不能由0改写为1,如果不擦除直接写入会对数据造成影响。

3.擦除必须按最小擦除单元进行。

我们Flash相对于EEPROM快的本质上原因之一,我们Flsah是按照块擦除,而对于EEPROM而言我们擦除是按字节擦除,所以Flash擦除非常快同时存取也非常快,也叫闪存。所以它有一个最小擦除单元,具体参照手册给出Sector Erase (4KB) :扇区擦除4kb

4.连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入;

以之前为例子我们每个学生归一个学校的一个院系管辖,不能超过这个学校跑别的学校的系,类似我们如果超过只会返回在本校开始第一个系当中。内存存储也是这样。

5.写入操作结束后,芯片进入忙状态,不响应新的读写操作;

芯片完成一次写入操作的时候,需要等待一会,我们就需要查询BUSY标志等待其消失。才能进行下次写入操作。

相对于写操作而言,读操作没有那么多要求,直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取。

唯一就是不能在忙状态读取,所以在写入操作以后我们需要进行等待,查询BUSY标志位等待其为0,不在处于忙状态才可以读取。

主要指令集在于指令集2:

主要是针对于不同模式的数据读取方式,读取速度不同,以及方式,具体参考手册。

参考历程如下:

W25Q64_INS.h:

#ifndef __W25Q64_INS_H
#define __W25Q64_INS_H

#define W25Q64_WRITE_ENABLE							       0x06
#define W25Q64_WRITE_DISABLE						       0x04
#define W25Q64_READ_STATUS_REGISTER_1				   0x05
#define W25Q64_READ_STATUS_REGISTER_2				   0x35
#define W25Q64_WRITE_STATUS_REGISTER				   0x01
#define W25Q64_PAGE_PROGRAM							       0x02
#define W25Q64_QUAD_PAGE_PROGRAM					     0x32
#define W25Q64_BLOCK_ERASE_64KB						     0xD8
#define W25Q64_BLOCK_ERASE_32KB						     0x52
#define W25Q64_SECTOR_ERASE_4KB						     0x20
#define W25Q64_CHIP_ERASE						         	 0xC7
#define W25Q64_ERASE_SUSPEND						       0x75
#define W25Q64_ERASE_RESUME							       0x7A
#define W25Q64_POWER_DOWN							         0xB9
#define W25Q64_HIGH_PERFORMANCE_MODE				   0xA3
#define W25Q64_CONTINUOUS_READ_MODE_RESET			 0xFF
#define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID	0xAB
#define W25Q64_MANUFACTURER_DEVICE_ID				   0x90
#define W25Q64_READ_UNIQUE_ID						0x4B
#define W25Q64_JEDEC_ID								0x9F
#define W25Q64_READ_DATA							0x03
#define W25Q64_FAST_READ							0x0B
#define W25Q64_FAST_READ_DUAL_OUTPUT				0x3B
#define W25Q64_FAST_READ_DUAL_IO					0xBB
#define W25Q64_FAST_READ_QUAD_OUTPUT				0x6B
#define W25Q64_FAST_READ_QUAD_IO					0xEB
#define W25Q64_OCTAL_WORD_READ_QUAD_IO				0xE3

#define W25Q64_DUMMY_BYTE							0xFF

#endif

W25Q64.c

#include "stm32f10x.h"                  // Device header
#include "MYSPI.h"
#include "W25Q64_lns.h"
/**
  * @brief  W25Q64初始化
  * @param  无形参
  * @retval 无返回值
  */
void W25Q64_Init(void)
{
	MYSPI_Init();
}


/**
  * @brief  W25Q64读取ID号
  * @param  MID:厂家ID
            DID:产品ID
  * @retval 无返回值
  */
void W25Q64_READ_ID(uint8_t* MID, uint16_t* DID)
{
	MYSPI_START();
	MYSPI_SwapByte(W25Q64_JEDEC_ID);
	*MID=MYSPI_SwapByte( W25Q64_DUMMY_BYTE);
	*DID=MYSPI_SwapByte( W25Q64_DUMMY_BYTE);
	*DID<<=8;
	*DID|=MYSPI_SwapByte(W25Q64_DUMMY_BYTE);
	MYSPI_STOP();
}


/**
  * @brief  W25Q64写使能
  * @param  无形参
  * @retval 无返回值
  */
void W25Q64_WriteEnable(void)
{
	MYSPI_START();
	MYSPI_SwapByte(W25Q64_WRITE_ENABLE);
	MYSPI_STOP();
}


/**
  * @brief  W25Q64等待BUSY结束
  * @param  无形参
  * @retval 无返回值
  */
void W25Q64_WaitBUSY(void)
{
	uint32_t TimeOut=1000;
	MYSPI_START();
	MYSPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);
	while((MYSPI_SwapByte(W25Q64_DUMMY_BYTE)&0x01)==0x01)
	{
		TimeOut--;
		if(TimeOut==0)
		{
			break;
		}
	}
	MYSPI_STOP();
}


/**
  * @brief  W25Q64擦除
  * @param  需要擦除的地址
  * @retval 无返回值
  */
void W25Q64_SectorErase(uint32_t address)
{
	W25Q64_WriteEnable();
	MYSPI_START();
	MYSPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);
	MYSPI_SwapByte(address>>16);
	MYSPI_SwapByte(address>>8);
	MYSPI_SwapByte(address);
	MYSPI_STOP();
	W25Q64_WaitBUSY();
}

/**
  * @brief  W25Q64写操作
  * @param  地址,写入数据,数据个数
  * @retval 无返回值
  */
void W25Q64_Wirte_Page(uint32_t address ,uint8_t*DataArray,uint16_t count)
{
	uint8_t n=0;
	W25Q64_WriteEnable();//写使能
  MYSPI_START();
	MYSPI_SwapByte(W25Q64_PAGE_PROGRAM);//发送写指令
	MYSPI_SwapByte(address>>16);//块
	MYSPI_SwapByte(address>>8);//扇
	MYSPI_SwapByte(address);//页
	for(n=0;n<count;n++)
	{
		MYSPI_SwapByte(DataArray[n]);
	}
	MYSPI_STOP();
	W25Q64_WaitBUSY();//等待忙碌结束,以待读取
}

/**
  * @brief  W25Q64普通读取
  * @param  地址,读取数据,数据个数
  * @retval 有无返回值
  */
void W25Q64_ReadData(uint32_t address,uint8_t* ReadData,uint32_t count)
{
	uint8_t n=0;
  MYSPI_START();
	MYSPI_SwapByte(W25Q64_READ_DATA);
	MYSPI_SwapByte(address>>16);
	MYSPI_SwapByte(address>>8);
	MYSPI_SwapByte(address);
	for(n=0;n<count;n++)
	{
		ReadData[n]=MYSPI_SwapByte(W25Q64_DUMMY_BYTE);
	}
	MYSPI_STOP();
}

测试main.c:

uint8_t MID;
uint16_t DID;
uint8_t DataArray[4]={0xA1,0xB2,0xC3,0xD4};
uint8_t ReadData[4];
int main(void)
{
	OLED_Init();		//OLED初始化
  W25Q64_Init();
	OLED_ShowString(1,1,"MID:");
	OLED_ShowString(2,1,"DID:");
	OLED_ShowString(3,1,"W:");
	OLED_ShowString(4,1,"R:");
	
	W25Q64_READ_ID(&MID,&DID);
	OLED_ShowHexNum(1,5,MID,2);
	OLED_ShowHexNum(2,5,DID,4);
	
	W25Q64_SectorErase(0x000000);
	
	W25Q64_Wirte_Page(0x000000 ,DataArray,4);
	W25Q64_ReadData(0x000000,ReadData,4);
	
	OLED_ShowHexNum(3,3,DataArray[0],2);
	OLED_ShowHexNum(3,6,DataArray[1],2);
	OLED_ShowHexNum(3,9,DataArray[2],2);
	OLED_ShowHexNum(3,12,DataArray[3],2);
	
	OLED_ShowHexNum(4,3,ReadData[0],2);
	OLED_ShowHexNum(4,6,ReadData[1],2);
	OLED_ShowHexNum(4,9,ReadData[2],2);
	OLED_ShowHexNum(4,12,ReadData[3],2);
	while (1)
	{

	}
}

实际运行结果如下:

具体参考手册为准,仅列出部分参考。

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

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

相关文章

x-cmd pkg | mermaid - 流程图、时序图等图表绘制工具

简介 mermaid-cli 是由 Mermaid 官方提供的命令行工具&#xff0c;用于将 Mermaid 语法的文本转换为 SVG / PNG / PDF。 Mermaid 是一个基于 JavaScript 的图表绘制工具&#xff0c;它使用简单的文本描述语法&#xff0c;就可以绘制出流程图、时序图、甘特图等多种图表。 首次…

跟着cherno手搓游戏引擎【6】ImGui和ImGui事件

导入ImGui&#xff1a; 下载链接&#xff1a; GitHub - TheCherno/imgui: Dear ImGui: Bloat-free Immediate Mode Graphical User interface for C with minimal dependencies 新建文件夹&#xff0c;把下载好的文件放入对应路径&#xff1a; SRC下的premake5.lua文件&#…

48 WAF绕过-权限控制之代码混淆及行为造轮子

目录 Safedog代码层手写及脚本绕过BT Aliyun代码层手写及脚本绕过safedog&#xff0c;BT&#xff0c;Aliyun-基于覆盖加密变异下编码解码绕过-代码层Safedog&#xff0c;BT&#xff0c;Aliyun-基于冰蝎新型控制器绕过全面测试-行为层Safedog,BT,Aliyun-基于手写新型控制器绕过全…

kotlin运行

1.使用android studio 由于我本身是做android的&#xff0c;android studio本身有内置kotlin的插件。但若只是想跑kotlin的程序&#xff0c;并不像和android程序绑在一起&#xff0c;可以创建一个kt文件&#xff0c;在里面写一个main函数&#xff0c;就可以直接运行kotlin程序…

如何隐藏服务器真实IP地址,隐藏服务器IP有什么好处

首先我们介绍了隐藏服务器IP的概念及工作模式&#xff0c;接着阐述了其对于DDoS攻击的防护作用。然后介绍了如何利用隐藏服务器IP增加系统性能和稳定性。接着我们讲述了如何隐藏服务器IP防止黑客攻击&#xff0c;最后总结了隐藏服务器IP在保护服务器和用户数据方面发挥的作用。…

10分钟读完一篇 AI 论文!​

已经2024年了&#xff0c;该出现一个写论文解读的AI Agent了。 大家肯定也在经常刷论文吧。 但真正尝试过用GPT去刷论文、写论文解读的小伙伴&#xff0c;一定深有体验——费劲。其他agents也没有能搞定的&#xff0c;今天我发现了一个超级厉害的写论文解读的agent &#xff…

计算机网络期末复习(基础概念+三套卷子练习)

文章目录 第一章&#xff1a;计算机网络概念计算机网络的概念计算机网络体系结构 第二章&#xff1a;物理层物理层的基本概念物理层的基本通信技术 练题专题练习码分多址地址聚合 1.0选择填空大题练习 2.0选择填空大题练习 3.0选择填空大题练习 第一章&#xff1a;计算机网络概…

【驱动】TI AM437x(内核调试-06):网卡(PHY和MAC)、七层OSI

1、网络基础知识 1.1 七层OSI 第一层:物理层。 1)需求: 两个电脑之间如何进行通信? 具体就是一台发比特流,另一台能够收到。于是就有了物理层:主要是定义设备标准,如网线的额接口类型、管线的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流,就是从1/0…

C++多线程学习[三]:成员函数作为线程入口

一、成员函数作为线程入口 #include<iostream> #include<thread> #include<string>using namespace std;class Mythread { public:string str;void Test(){cout << str << endl;} }; int main() {Mythread test;test.str "Test";thr…

tidb Cloud 连接spring boot 项目

一、 免费试用tidbitcloud TiDB Cloud Documentation | PingCAP Docs 1.github账号登录 2.创建集群 3.点击对应集群cludter0 导入数据 导入 本地导入只支持csv文件&#xff0c;其他导入需要AWZ账号使用S3云存储 二、连接spingboot项目 选择java&#xff0c;复制下面的jd…

Matlab并行编程之GPU

Matlab并行编程之GPU Matlab提供GPU上计算支持: 基础数据类型(gpuArray和对应API),支持GPU计算的内置函数和多个工具包,支持PTX内核对象加载,支持MEX函数使用CUDA C/C开发等。对大规模数据处理&#xff0c;复杂计算&#xff0c;利用GPU计算能提供显著的性能加速效果. Matlab同…

Django教程第5章 | Web开发实战-数据统计图表(echarts、highchart)

专栏系列&#xff1a;Django学习教程 前言 highchart&#xff0c;国外。 echarts&#xff0c;国内。 本项目集成 hightchart和echarts图表库实现数据统计功能。 包括&#xff1a;折线图&#xff0c;柱状图&#xff0c;饼图和数据集图。 效果图 echats Highcharts 源代码…

BitLocker 驱动器加密

BitLocker 简介 BitLocker 驱动器加密是一项由微软开发并集成在Windows操作系统中的数据保护功能&#xff0c;其主要作用是通过加密存储在硬盘驱动器上的数据来增强信息安全。具体来说&#xff1a; 数据安全&#xff1a;BitLocker可以对整个操作系统卷&#xff08;包括系统分区…

【Unity实战100例】Unity对Ini格式的配置文件管理和读写

目录 一.编写ini格式配置文件 二.读取解析ini文件 三.调用属性 INI 文件以文本形式存储,易于阅读和编辑。这种人可读的格式使得调整配置参数变得更加直观,不需要专门的工具。 INI 文件是一种轻量级的配置文件格式,不需要复杂的解析器或库。它的结构相对简单,适用于小到

Jenkins自动化部署docker

Jenkins自动化部署docker和普通方式构建 docker外挂目录 准备测试服务器docker环境准备jdk环境将上传jar包修改为app.jar对外暴露1000端口启动jar FROM openjdk:8-jdk-alpine ARG JAR_FILE COPY ${JAR_FILE} app.jar EXPOSE 1000 ENTRYPOINT ["java","-jar&q…

生产力与生产关系 —— 浅析爱泼斯坦事件 之 弱电控制强电原理

据网络文字与视频资料&#xff0c;爱泼斯坦事件是犹太精英阶层&#xff0c;为了掌控美国国家机器为犹太利益集团服务&#xff0c;而精心设下的一个局。本文先假设这个结论成立&#xff0c;并基于此展开讨论。 我们知道&#xff0c;弱电管理强电是电气工程中的一门专门学问&…

使用CloudFlare-Woker搭建简易网站

使用CloudFlare-Woker搭建简易网站 1、首先到CloudFlare官网登录或注册自己的账号&#xff1a;Cloudflare 中国官网 | 智能化云服务平台 | 免费CDN安全防护 | Cloudflare (cloudflare-cn.com) 注册一个账号 2、登录账号后进入仪表盘网页&#xff0c;选择Workers & Pages页…

目标检测DETR:End-to-End Object Detection with Transformers

NMS 对一个目标生成了多个检测窗口&#xff0c;但是事实上这些窗口中大部分内容都是重复的&#xff0c;找到目标检测最优的窗口 选取多个检测窗口中分数最高的窗口&#xff0c;剔除掉其他同类型的窗口 anchor generator 首先在该点生成scale512, aspect ratio{1:2&#xff…

Xtuner实战+LLM微调

Finetune 微调 在实际对话中&#xff0c;通常会有三种角色 system&#xff1a;给定一些上下文信息&#xff0c;“你是一个专业的内科医生&#xff0c;能回答医疗领域的专业问题”User&#xff1a;用户的问题&#xff0c;”肿瘤如何治疗“Assistant&#xff1a;LLM的回答 增量…

Unity3D学习之数据持久化——PlayerPrefs

文章目录 1. 概念2. 存储2.1 存到内存当中2.2 存到硬盘当中2.3 局限性2.4 相同键会覆盖 3.读取3.1 int型3.2 float型3.3 string型3.4 判断数据是否存在 4. 删除数据5. 存储位置6. 反射6.1 判断一个类型的对象是否可以让另一个类型为自己分配空间6.2 通过反射获得泛型类型 7 数据…