通用外设-W25Q64

前言

一、SPI通信

二、W25Q64基初时序

1.各种命令代码

2.代码

1.写使能指令

2.读取芯片是否忙碌状态并等待

3.写入数据

4.擦除函数操作

5.读取代码

三.验证

四.擦除说明

总结


前言

在单片机中一般32K FLASH就够用了,但是当我们使用图片或其他大量数据时就不够用了,又因为数据为固定数据,不需要为此而换大容量芯片。因此用外挂存储芯片来解决这个问题。

本篇文章采用SPI软件通信的方式进行讲解,了解存储芯片同时加深SPI通信了解。

环境:

芯片:STM32F103C8T6

Keil:V5.24.2.0

外设:4针OLED屏,W25Q64芯片


一、SPI通信

关于SPI通信简介看我之前文章:

写文章-CSDN创作中心

还包含了读ID指令。本篇就不在赘述。

二、W25Q64基初时序

1.各种命令代码

标黄色的为重要代码,我们应尽量掌握。

各个代码进行宏定义,方便我们使用,也方便我们以后查阅

#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        //无用数据(不是无用)

2.代码

1.写使能指令

在写入数据时必须进行的操作,防止误操作

void W25Q64_WriteEnable(void)		//书写使能命令
{
	MySPI_Start();
	MySPI_SwapByte(W25Q64_WRITE_ENABLE);
	MySPI_Stop();
}

2.读取芯片是否忙碌状态并等待

也是比较简单:

开始传输,发送读取指令,等待芯片忙碌结束,停止。

void W25Q64_WaitBusy(void)		//读取芯片是否忙碌状态并等待
{
	uint32_t Timeout;
	MySPI_Start();
	MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);
	Timeout =1000000;			//防死循环措施,时间可以加长
	while((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01)
	{
		Timeout --;
		if(Timeout == 0)
		{
			break;
		}
	}
	MySPI_Stop();
}

3.写入数据

1.地址:指定写入的地址

2.数据:需要写入的数据,根据芯片描述,每页写入数据不大于64K,大于64K需要进行分页写入

3.数组的大小,方便进行循环

/**************************
@:地址
@:要写入的数据
@:数组数
***************************/
void W25Q64_PageProgram(uint32_t Address,uint32_t *DataArray,uint16_t Count)//写入代码
{
	uint16_t i;
	
	W25Q64_WriteEnable();
	
	MySPI_Start();
	MySPI_SwapByte(W25Q64_PAGE_PROGRAM);
	MySPI_SwapByte(Address >> 16);	//总共24位地址,右移16后剩高8位
	MySPI_SwapByte(Address >> 8);	//右移8位后剩高位16,但是只能发送8位,高8位舍弃
	MySPI_SwapByte(Address);
	for(i = 0;i < Count ;i ++)	//对数组进行写入
	{
		MySPI_SwapByte(DataArray[i]);
	}
	MySPI_Stop();
	
	W25Q64_WaitBusy();				//等待芯片空闲,在读写后进行等待

注:因为芯片写入数据需要时间,不是我们MCU发送完那边就全部写入了。因此我们要等待其数据全部存储完,不然后果就是我们的下次写入操作会数据不准确。当然我们也可以把这行代码放在操作函数前。判断芯片是否忙碌状态。

4.擦除函数操作

 代码注释较全。

void W25Q64_SectorErase(uint32_t Address)	//擦除函数操作
{
	W25Q64_WriteEnable();
	W25Q64_WaitBusy();
	
	MySPI_Start();
	MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);
	MySPI_SwapByte(Address >> 16);	//总共24位地址,右移16后剩高8位
	MySPI_SwapByte(Address >> 8);	//右移8位后剩高位16,但是只能发送8位,高8位舍弃
	MySPI_SwapByte(Address);
	MySPI_Stop();
	
	W25Q64_WaitBusy();				//等待芯片空闲,需要在读写后进行等待
}

5.读取代码

void W25Q64_ReadData(uint32_t Address,uint32_t *DataArray,uint32_t Count)//读取代码
{
	uint32_t i;
	W25Q64_WaitBusy();
	MySPI_Start();

	MySPI_SwapByte(W25Q64_READ_DATA);
	MySPI_SwapByte(Address >> 16);	//总共24位地址,右移16后剩高8位
	MySPI_SwapByte(Address >> 8);	//右移8位后剩高位16,但是只能发送8位,高8位舍弃
	MySPI_SwapByte(Address);
	for(i = 0;i < Count ;i++)
	{
		DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE);//以此来置换回需要的数据
	}
	MySPI_Stop();
}

三.验证

写入和读取

uint32_t ArrayWrite[] = {0x01,0x02,0x03};
uint32_t ArrayRead[3];

int main(void)
{	
	OLED_Init();
	W25Q64_Init();
	
	W25Q64_SectorErase(0x000000);        //擦除操作
	W25Q64_PageProgram(0x000000,ArrayWrite,3);        //写入数据
	W25Q64_ReadData(0x000000,ArrayRead,3);        读取数据
	
	OLED_ShowHexNum(2, 1, ArrayWrite[0], 2);    //显示写入的三个数据
	OLED_ShowHexNum(2, 5, ArrayWrite[1], 2);
	OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);
	
	OLED_ShowHexNum(3, 1, ArrayRead[0], 2);       //显示读取的三个数据
	OLED_ShowHexNum(3, 5, ArrayRead[1], 2);
	OLED_ShowHexNum(3, 9, ArrayRead[2], 2);
	
	while (1)
	{
		
	}
}

四.擦除说明

因芯片设计问题,数据在写入时,只能从1转为0,不可以从0转为1,如果要想从0 转为1,就只能进行擦除作业。擦除分整个擦除,扇区,块擦除三个等级,范围大小不一样,看需要进行操作

因此。我们在写入数据前应尽量进行扇区擦除来保证数据的准确性。大家可以屏闭擦除函数进行验证。


总结

W25Q64芯片存储数据还是比较好用,原理比较清楚。但还是有一些问题待解决

1.写入大数据(如200KB)而MCU除了必要的程序数据(不包含要写入W25Q64的数据)外还剩40K数据。我们需要对200K数据进行5次分割才能写入数据,比较麻烦且不方便量产

2.因芯片每页数据最大64K,因此我们还需对数据进行准确分割,不能超过。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

支持华为GaussDB数据库的免费开源ERP:人力资源管理解决方案概述

开源智造所推出的Odoo SuperPeople数字化解决方案将HR和薪资数据与财务、项目规划、预算和采购流程连接起来&#xff0c;消除了多套系统给企业带来的信息孤岛问题。 ——复星集团 人力资源中心 高经理 一种更具吸引力、更有洞察力的人员管理方式 什么是开源智造Odoo的人力资源…

每日一练:LeeCode-102、二又树的层序遍历【二叉树】

本文是力扣LeeCode-102、二又树的层序遍历 学习与理解过程&#xff0c;本文仅做学习之用&#xff0c;对本题感兴趣的小伙伴可以出门左拐LeeCode。 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&…

【数据结构】哈希表详解,举例说明 java中的 HashMap

一、哈希表&#xff08;Hash Table&#xff09;简介&#xff1a; 哈希表是一种数据结构&#xff0c;用于实现字典或映射等抽象数据类型。它通过把关键字映射到表中的一个位置来实现快速的数据检索。哈希表的基本思想是利用哈希函数将关键字映射到数组的索引位置上&#xff0c;…

java多线程(并发)夯实之路-volatile深入浅出

volatile volatile&#xff08;易变关键字&#xff09;可以用来修饰成员变量和静态成员变量&#xff0c;线程只能从主存中获取它的值&#xff0c;线程操作volatile变量都是直接操作主存 与synchronzied区别&#xff1a;synchronzied需要创建Monitor&#xff0c;属于重量级的操…

读书笔记——《未来简史》

前言 《未来简史》是以色列历史学家尤瓦尔赫拉利的人类简史三部曲之一。三部分别为《人类简史》《未来简史》《今日简史》。其中最为著名的当然是《人类简史》&#xff0c;非常宏大的一本关于人类文明历史的书籍&#xff0c;绝对可以刷新历史观&#xff0c;《人类简史》这本书…

DAY01_Spring—Spring框架介绍IOCSpring工厂模式

目录 1 什么是框架2 Spring框架2.1 Spring介绍2.2 MVC模型说明2.3 IOC思想2.3.1 问题说明2.3.2 IOC说明 3 Spring IOC具体实现3.1 环境准备3.1.1 关于JDK说明3.1.2 检查JDK环境配置 3.2 创建项目3.3 关于Maven 命令3.3.1 install 命令3.3.2 clean 命令 3.4 添加jar包文件3.4.1 …

云计算平台建设总体技术方案详细参考

第1章. 基本情况 1.1. 项目名称 XX 公司 XX 云计算平台工程。 1.2. 业主公司 XX 公司。 1.3. 项目背景 1.3.1. XX 技术发展方向 XX&#xff0c;即运用计算机、网络和通信等现代信息技术手段&#xff0c;实现政府组织结构和工作流程的优化重组&#xff0c;超越时间、空间…

【AIGC入门一】Transformers 模型结构详解及代码解析

Transformers 开启了NLP一个新时代&#xff0c;注意力模块目前各类大模型的重要结构。作为刚入门LLM的新手&#xff0c;怎么能不感受一下这个“变形金刚的魅力”呢&#xff1f; 目录 Transformers ——Attention is all You Need 背景介绍 模型结构 位置编码 代码实现&…

设计模式之开闭原则:如何优雅地扩展软件系统

在现代软件开发中&#xff0c;设计模式是解决常见问题的最佳实践。其中&#xff0c;开闭原则作为面向对象设计的六大基本原则之一&#xff0c;为软件系统的可维护性和扩展性提供了强大的支持。本文将深入探讨开闭原则的核心理念&#xff0c;以及如何在实际项目中运用这一原则&a…

Rust-借用和生命周期

生命周期 一个变量的生命周期就是它从创建到销毁的整个过程。其实我们在前面已经注意到了这样的现象&#xff1a; 然而&#xff0c;如果一个变量永远只能有唯一一个入口可以访问的话&#xff0c;那就太难使用了。因此&#xff0c;所有权还可以借用。 借用 变量对其管理的内存…

C#编程-自定义属性

命名自定义属性 让我们继续漏洞修复示例,在这个示例中新的自定义属性被命名为BugFixingAttribute。通常的约定是在属性名称后添加单词Attribute。编译器通过允许您调用具有短版名称的属性来支持附加。 因此,可以如以下代码段所示编写该属性: [ BugFixing ( 122,"Sara…

C#用double.TryParse(String, Double)方法将字符串类型数字转换为数值类型

目录 一、定义 二、实例 命名空间: System 程序集: System.Runtime.dll 一、定义 将数字的字符串表示形式转换为它的等效双精度浮点数。 一个指示转换是否成功的返回值。 public static bool TryParse (string? s, out double result…

蓝桥杯备赛 | 洛谷做题打卡day3

蓝桥杯备赛 | 洛谷做题打卡day3 sort函数真的很厉害&#xff01; 文章目录 蓝桥杯备赛 | 洛谷做题打卡day3sort函数真的很厉害&#xff01;【深基9.例1】选举学生会题目描述输入格式输出格式样例 #1样例输入 #1 样例输出 #1 我的一些话 【深基9.例1】选举学生会 题目描述 学校…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-2 常用表单控件

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>常用表单控件</title> <style> form {width: 260px;margin: 0 auto;border: 1px solid #ccc;padding: 20px; } .right {float: right; } </style&g…

【学习笔记】2、逻辑代数与硬件描述语言基础

2.1 逻辑代数 &#xff08;1&#xff09;逻辑代数的基本定律和恒等式 基本定律或 “”与 “”非 “—”0-1律A0AA11AAAA A ‾ \overline{A} A1(互补律)A00A1AAAAA A ‾ \overline{A} A0 A ‾ ‾ \overline{\overline{A}} AA结合律(AB)C A(BC)(AB)CA(BC)ABC交换律AB BAABBA分…

广州市生物医药及高端医疗器械产业链大会暨联盟会员大会召开,天空卫士数据安全备受关注

12月20日&#xff0c;广州市生物医药及高端医疗器械产业链大会暨联盟会员大会在广州举办。在本次会议上&#xff0c;作为大会唯一受邀参加主题分享的技术供应商&#xff0c;天空卫士南区技术总监黄军发表《生物制药企业如何保护数据安全》的主题演讲。 做好承上启下“连心桥”…

【Spring实战】29 @Value 注解

文章目录 1. 定义2. 好处3. 示例1&#xff09;注入基本类型2&#xff09;注入集合类型3&#xff09;使用默认值4&#xff09;注入整数和其他类型 总结 在实际的应用中&#xff0c;我们经常需要从外部配置文件或其他配置源中获取参数值。Spring 框架提供了 Value 注解&#xff0…

感染了后缀为.mallox勒索病毒如何应对?数据能够恢复吗?

尊敬的读者&#xff1a; 在数字时代&#xff0c;勒索病毒如.mallox已经成为网络威胁中的重要一环。这篇文章将深入介绍.mallox勒索病毒的特征、应对策略以及如何预防这一威胁。面对复杂的勒索病毒&#xff0c;您需要数据恢复专家作为坚强后盾。我们的专业团队&#xff08;技术…

adb wifi 远程调试 安卓手机 命令

使用adb wifi 模式调试需要满足以下前提条件&#xff1a; 手机 和 PC 需要在同一局域网下。手机需要开启开发者模式&#xff0c;然后打开 USB 调试模式。 具体操作步骤如下&#xff1a; 将安卓手机通过 USB 线连接到 PC。&#xff08;连接的时候&#xff0c;会弹出请求&#x…

收银系统源码-智慧新零售系统框架

智慧新零售系统是一套线下线上打通的收银系统&#xff0c;主要给门店提供含线下收银、线上小程序商城、ERP进销存、精细化会员管理、丰富营销插件等为一体的智慧行业解决方案。智慧新零售系统有合伙人、代理商、商户、门店、收银员/导购员等角色&#xff0c;每个角色有相应的权…