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|=SPI_ReadWriteByte(0xFF)<<16;
ID|=SPI_ReadWriteByte(0xFF)<<8;
ID|=SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return ID;
}
W25N04KV 设备ID 如下:
4. 写使能和写禁止
写使能
具体代码如下:
void Flash_Write_Enable(void) //写使能
{
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x06);//发送写使能命令
Flash_CS(1); //取消片选
}
写禁止
具体代码如下:
void Flash_Write_Disable(void) //写禁止
{
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x04);//发送写禁止命令
Flash_CS(1); //取消片选
}
5. 读写状态寄存器
读状态寄存器
具体代码如下:
uint8_t Flash_ReadSR1(void)//读取状态1寄存器
{
uint8_t SR = 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x05);
SPI_ReadWriteByte(0xA0);
SR = SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return SR;
}
uint8_t Flash_ReadSR2(void)//读取状态2寄存器
{
uint8_t SR = 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x05);
SPI_ReadWriteByte(0xB0);
SR = SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return SR;
}
uint8_t Flash_ReadSR3(void)//读取状态3寄存器
{
uint8_t SR = 0;
Flash_CS(0); //使能片选
SPI_ReadWriteByte(0x05);
SPI_ReadWriteByte(0xC0);
SR = SPI_ReadWriteByte(0xFF);
Flash_CS(1); //取消片选
return SR;
}
写状态寄存器
具体代码如下:
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); //取消片选
}
等待空闲
具体代码如下:
void Flash_Wait_Busy(void)
{
while((Flash_ReadSR3()&0x01)==0x01); // 等待BUSY位清空
}
6. 块擦除
在执行擦除命令前,需要先清除写保护,然后使能写入,方可擦除成功。
具体代码如下:
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 的读数据主要分两步:
(1)读Flash数据到缓存区,一次读一页,2k字节。
(2)读取缓存区的数据
具体代码如下:
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=0;i<NumByteToRead;i++)
{
pBuffer[i]=SPI_ReadWriteByte(0xFF); //循环读数
}
Flash_CS(1);//取消片选
}
8. 写数据
在执行写命令前,需要先清除写保护,然后使能写入,方可写成功。
W25N04KV 的写数据主要分两步:
(1)先把数据写入缓存页
- 0x02 指令:先清除缓存区然后写入数据。
- 0x84 指令:不会清除缓存区的数据,直接写入数据。
(2)然后把缓存页中的数据写入Flash
具体代码如下:
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=0;i<NumByteToWrite;i++)
{
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();//禁止写入
}