热门标签 | 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();//禁止写入
}








推荐阅读
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 配置IPv4静态路由实现企业网内不同网段用户互访
    本文介绍了通过配置IPv4静态路由实现企业网内不同网段用户互访的方法。首先需要配置接口的链路层协议参数和IP地址,使相邻节点网络层可达。然后按照静态路由组网图的操作步骤,配置静态路由。这样任意两台主机之间都能够互通。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 达人评测 酷睿i5 12450h和锐龙r7 5800h选哪个好 i512450h和r75800h对比
    本文介绍了达人评测酷睿i5 12450h和锐龙r7 5800h选哪个好的相关知识,包括两者的基本配置和重要考虑点。希望对你在选择时提供一定的参考价值。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
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社区 版权所有