热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【HAL库】STM32CubeMX开发STM32F407读写W25N04KV外部Flash

STM32CubeMX下载和安装详细教程【HAL库】STM32CubeMX开发----STM32F407----目录一、W25N04KV简介W25N04KV是NANDFlash系


STM32CubeMX 下载和安装 详细教程
【HAL库】STM32CubeMX开发----STM32F407----目录




一、W25N04KV 简介

W25N04KV 是 NAND Flash系列的,具有高存储密度,并且写入和擦除的速度也很快。W25N04KV 内存为:4G(bit)/512M(byte)


特点

在这里插入图片描述


芯片封装和引脚分配

在这里插入图片描述


内存框图和寻址方式

在这里插入图片描述

W25N04KV 的寻址方式:页地址+列地址(Page Address + Column Address)


  • 列地址---- Column Address(CA)[11:0]
    列地址大小 2176 (字节),由 2048(字节)数据缓存区128(字节) 备用区域 组成。

  • 页地址---- Page Address(PA)[17:0]
    页地址包括 4096 (块) x 64(页)

W25N04KV 整个 Flash 共有4096块(Block),每块包含64页(Page),每页大小为 2048(字节)。(一共4096x64x2048=512M)


寄存器

W25N04KV 提供三个寄存器,分别是:保护寄存器(SR1),配置寄存器(SR2)状态寄存器(SR3)


保护寄存器(SR1)

在这里插入图片描述


配置寄存器(SR2)

在这里插入图片描述


状态寄存器(SR3)

在这里插入图片描述


二、W25N04KV 程序实现命令

1. SPI 底层驱动读写程序

具体代码如下:

uint8_t SPI_ReadWriteByte(uint8_t TxData)
{
uint8_t Rxdata;
HAL_SPI_TransmitReceive(&hspi1,&TxData,&Rxdata,1, 1000);
return Rxdata;
}

2. 常用命令表

在这里插入图片描述


3. 读 W25N04KV 设备ID

读 W25N04KV 设备ID的命令如下:

在这里插入图片描述
在这里插入图片描述
具体程序如下:

uint32_t Flash_ReadID(void)//读取外部Flash芯片ID
{
uint32_t ID = 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x9F);//发送读取ID命令
SPI_ReadWriteByte(0x00);
ID|&#61;SPI_ReadWriteByte(0xFF)<<16;
ID|&#61;SPI_ReadWriteByte(0xFF)<<8;
ID|&#61;SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return ID;
}

W25N04KV 设备ID 如下&#xff1a;

在这里插入图片描述


4. 写使能和写禁止

在这里插入图片描述


写使能

在这里插入图片描述
具体代码如下&#xff1a;

void Flash_Write_Enable(void) //写使能
{
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x06);//发送写使能命令
Flash_CS(1); //取消片选
}

写禁止

在这里插入图片描述
具体代码如下&#xff1a;

void Flash_Write_Disable(void) //写禁止
{
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x04);//发送写禁止命令
Flash_CS(1); //取消片选
}

5. 读写状态寄存器


读状态寄存器

在这里插入图片描述
在这里插入图片描述

具体代码如下&#xff1a;

uint8_t Flash_ReadSR1(void)//读取状态1寄存器
{
uint8_t SR &#61; 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x05);
SPI_ReadWriteByte(0xA0);
SR &#61; SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return SR;
}
uint8_t Flash_ReadSR2(void)//读取状态2寄存器
{
uint8_t SR &#61; 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x05);
SPI_ReadWriteByte(0xB0);
SR &#61; SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return SR;
}
uint8_t Flash_ReadSR3(void)//读取状态3寄存器
{
uint8_t SR &#61; 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x05);
SPI_ReadWriteByte(0xC0);
SR &#61; SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return SR;
}

写状态寄存器

在这里插入图片描述
在这里插入图片描述
具体代码如下&#xff1a;

void Flash_WriteSR1(uint8_t Sdata)//写状态1寄存器
{
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x01);
SPI_ReadWriteByte(0xA0);
SPI_ReadWriteByte(Sdata);
Flash_CS(1); //取消片选
}
void Flash_WriteSR2(uint8_t Sdata)//写状态2寄存器
{
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x01);
SPI_ReadWriteByte(0xB0);
SPI_ReadWriteByte(Sdata);
Flash_CS(1); //取消片选
}

等待空闲

在这里插入图片描述
具体代码如下&#xff1a;

void Flash_Wait_Busy(void)
{
while((Flash_ReadSR3()&0x01)&#61;&#61;0x01); // 等待BUSY位清空
}

6. 块擦除

在执行擦除命令前&#xff0c;需要先清除写保护&#xff0c;然后使能写入&#xff0c;方可擦除成功。

在这里插入图片描述
在这里插入图片描述
具体代码如下&#xff1a;

void Flash_Block_Erase(uint32_t BlockAddr)
{
Flash_WriteSR1(0x00); //清除写保护
Flash_Write_Enable(); //写使能

Flash_CS(0); //使能器件
SPI_ReadWriteByte(0xD8);//块擦除
SPI_ReadWriteByte((uint8_t)((BlockAddr)>>16));
SPI_ReadWriteByte((uint8_t)((BlockAddr)>>8));
SPI_ReadWriteByte((uint8_t)BlockAddr);
Flash_CS(1); //取消片选
Flash_Wait_Busy(); //等待BUSY位清空
Flash_Write_Disable(); //禁止写入
}

7. 读数据

W25N04KV 的读数据主要分两步&#xff1a;

&#xff08;1&#xff09;读Flash数据到缓存区&#xff0c;一次读一页&#xff0c;2k字节。
在这里插入图片描述
在这里插入图片描述

&#xff08;2&#xff09;读取缓存区的数据
在这里插入图片描述
在这里插入图片描述
具体代码如下&#xff1a;

void Flash_Read(uint8_t* pBuffer,uint32_t PageAddr,uint16_t ColumnAddr,uint16_t NumByteToRead)
{
Flash_CS(0);//使能器件
SPI_ReadWriteByte(0x13); //发送页读取命令
SPI_ReadWriteByte((uint8_t)((PageAddr)>>16));
SPI_ReadWriteByte((uint8_t)((PageAddr)>>8));
SPI_ReadWriteByte((uint8_t)PageAddr);
Flash_CS(1);//取消片选

delay_us(50);//两条命令之间至少50us延时

Flash_CS(0);//使能器件
SPI_ReadWriteByte(0x03); //发送读取命令
SPI_ReadWriteByte((uint8_t)((ColumnAddr)>>8));
SPI_ReadWriteByte((uint8_t)ColumnAddr);
SPI_ReadWriteByte(0x00);
for(uint16_t i&#61;0;i<NumByteToRead;i&#43;&#43;)
{
pBuffer[i]&#61;SPI_ReadWriteByte(0xFF); //循环读数
}
Flash_CS(1);//取消片选
}

8. 写数据

在执行写命令前&#xff0c;需要先清除写保护&#xff0c;然后使能写入&#xff0c;方可写成功。

W25N04KV 的写数据主要分两步&#xff1a;

&#xff08;1&#xff09;先把数据写入缓存页


  • 0x02 指令&#xff1a;先清除缓存区然后写入数据。
  • 0x84 指令&#xff1a;不会清除缓存区的数据&#xff0c;直接写入数据。

在这里插入图片描述
在这里插入图片描述

&#xff08;2&#xff09;然后把缓存页中的数据写入Flash

在这里插入图片描述
在这里插入图片描述
具体代码如下&#xff1a;

void Flash_Write_Page(uint8_t* pBuffer,uint32_t PageAddr,uint16_t ColumnAddr,uint16_t NumByteToWrite)
{
Flash_WriteSR1(0x00);//清除写保护
Flash_Write_Enable();//写使能

Flash_CS(0); //使能器件
SPI_ReadWriteByte(0x02); //装载数据到缓存区
SPI_ReadWriteByte((uint8_t)((ColumnAddr)>>8));
SPI_ReadWriteByte((uint8_t)ColumnAddr);
for(uint16_t i&#61;0;i<NumByteToWrite;i&#43;&#43;)
{
SPI_ReadWriteByte(pBuffer[i]); //循环写数
}
Flash_CS(1);//取消片选

delay_us(50);//两条命令之间至少50us延时

Flash_CS(0);//使能器件
SPI_ReadWriteByte(0x10); //装载缓存区数据到物理页
SPI_ReadWriteByte((uint8_t)((PageAddr)>>16));
SPI_ReadWriteByte((uint8_t)((PageAddr)>>8));
SPI_ReadWriteByte((uint8_t)PageAddr);
Flash_CS(1); //取消片选
Flash_Wait_Busy();//等待BUSY位清空
Flash_Write_Disable();//禁止写入
}








推荐阅读
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
  • Netty框架中运用Protobuf实现高效通信协议
    在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。 ... [详细]
  • 本文深入解析了Bitmap与Byte数组之间高效转换的方法,探讨了不同场景下的最优实现策略,提供了详尽的代码示例和性能对比分析,旨在帮助开发者在图像处理和数据传输中提升效率和减少资源消耗。 ... [详细]
  • 在过去,我曾使用过自建MySQL服务器中的MyISAM和InnoDB存储引擎(也曾尝试过Memory引擎)。今年初,我开始转向阿里云的关系型数据库服务,并深入研究了其高效的压缩存储引擎TokuDB。TokuDB在数据压缩和处理大规模数据集方面表现出色,显著提升了存储效率和查询性能。通过实际应用,我发现TokuDB不仅能够有效减少存储成本,还能显著提高数据处理速度,特别适用于高并发和大数据量的场景。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 提升Android开发效率:Clean Code的最佳实践与应用
    在Android开发中,提高代码质量和开发效率是至关重要的。本文介绍了如何通过Clean Code的最佳实践来优化Android应用的开发流程。以SQLite数据库操作为例,详细探讨了如何编写高效、可维护的SQL查询语句,并将其结果封装为Java对象。通过遵循这些最佳实践,开发者可以显著提升代码的可读性和可维护性,从而加快开发速度并减少错误。 ... [详细]
  • 第二章:Kafka基础入门与核心概念解析
    本章节主要介绍了Kafka的基本概念及其核心特性。Kafka是一种分布式消息发布和订阅系统,以其卓越的性能和高吞吐量而著称。最初,Kafka被设计用于LinkedIn的活动流和运营数据处理,旨在高效地管理和传输大规模的数据流。这些数据主要包括用户活动记录、系统日志和其他实时信息。通过深入解析Kafka的设计原理和应用场景,读者将能够更好地理解其在现代大数据架构中的重要地位。 ... [详细]
  • SQLite数据库CRUD操作实例分析与应用
    本文通过分析和实例演示了SQLite数据库中的CRUD(创建、读取、更新和删除)操作,详细介绍了如何在Java环境中使用Person实体类进行数据库操作。文章首先阐述了SQLite数据库的基本概念及其在移动应用开发中的重要性,然后通过具体的代码示例,逐步展示了如何实现对Person实体类的增删改查功能。此外,还讨论了常见错误及其解决方法,为开发者提供了实用的参考和指导。 ... [详细]
  • HBase Java API 进阶:过滤器详解与应用实例
    本文详细探讨了HBase 1.2.6版本中Java API的高级应用,重点介绍了过滤器的使用方法和实际案例。首先,文章对几种常见的HBase过滤器进行了概述,包括列前缀过滤器(ColumnPrefixFilter)和时间戳过滤器(TimestampsFilter)。此外,还详细讲解了分页过滤器(PageFilter)的实现原理及其在大数据查询中的应用场景。通过具体的代码示例,读者可以更好地理解和掌握这些过滤器的使用技巧,从而提高数据处理的效率和灵活性。 ... [详细]
  • 基址获取与驱动开发:内核中提取ntoskrnl模块的基地址方法解析
    基址获取与驱动开发:内核中提取ntoskrnl模块的基地址方法解析 ... [详细]
  • 在MySQL中实现时间比较功能的详细解析与应用
    在MySQL中实现时间比较功能的详细解析与应用。本文深入探讨了MySQL中时间比较的实现方法,重点介绍了`UNIX_TIMESTAMP`函数的应用。该函数可以接收一个日期时间参数,也可以不带参数使用,其返回值为Unix时间戳,便于进行时间的精确比较和计算。此外,文章还涵盖了其他相关的时间处理函数和技巧,帮助读者更好地理解和掌握MySQL中的时间操作。 ... [详细]
  • 在使用Keil C51创建51单片机项目时,启动代码中包含多个关键元素,这些元素确保了系统的正确初始化和运行。主要包括复位向量、中断向量表、系统时钟配置、寄存器初始化以及主函数入口等。这些组件共同协作,为后续的应用程序执行提供稳定的基础。 ... [详细]
  • 本文详细探讨了Java事件处理机制的核心概念与实现原理,内容浅显易懂,适合初学者逐步掌握。通过具体的示例和详细的解释,读者可以深入了解Java事件模型的工作方式及其在实际开发中的应用。 ... [详细]
  • 如何在系统设置中找到高级配置选项 ... [详细]
author-avatar
PHPdudu
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有