W25Q64 SPI Flash 核心知识点超全总结 | 从基础原理到操作时序
一、W25Q64概述
W25Q64是华邦(winbond)退出的SPI接口非易失性FLASH存储心器,核心 特性与定位如下
1、核心容量:64M-bit = 8M-byte,远大于AT24C02这类百字节的容量,且最高通信速度为80Mhz
2、核心特效:掉电数据不丢失
3、典型用途:常用语存放不修改的大体积数据,字库文件,音频文件,图片,系统固件等等
二、核心存储结构与地址规则
1、基础存储单位

2、地址规则
2.1、地址范围:24位绝对地址,范围为0x000000 ~ 0x7FFFFF ,共8Mb空间,每个绝对固定地址固定存放1Byte数据
2.2、地址拆解:24位地址拆解可以按存储层级拆解为:块号(2位)+扇区号(1位)
+ 页号(1位)+字节偏移(2位)
2.3、地址计算示例:

三、擦除与写入核心特性
1、核心写入原理:W25Q64在写入时,只能将数据位的1改写为0,无法将0改写为1
2、擦除的本质:将指定存储空间内的所有数据位全部置1,为后续写入做准备
3、硬性规则:写入新数据之前,必须先擦除目标地址所在的存储空间,否则报错
4、支持的4种擦除方式:
1)扇区擦除:最小颗粒度,4kb空间
2)半块 擦除:32KB空间
3)块擦除:64KB空间
4)全片擦除:擦除整个8MB存储空间
四、芯片管脚的功能

五、指令表

六、代码(写使能、读空闲函数、擦除函数、页写函数、连续读函数、跨页写函数)
1、写使能

/*************************
函数名称:w25_Wr_Enable(void)
函数功能:w25写使能函数
返回值:无
形参:无
作者:me
版本:1.0
*************************/
void w25_Wr_Enable(void)
{
//拉低,接收
W25Q64_CS_L;
//发送0x06 写使能指令
Spi1_Change_By(0x06);
//拉高停止
W25Q64_CS_H;
}
2、读空闲函数

/*************************
函数名称:w25_Re_Free(void)
函数功能:w25读空闲函数 返回为0是空闲
返回值:u8
形参:无
作者:me
版本:1.0
*************************/
u8 w25_Re_Free(void)
{
u8 temp;
//拉低,接收
W25Q64_CS_L;
//发送读函数指令
Spi1_Change_By(0x05);
//接收数据
temp = Spi1_Change_By(0xff);
//拉高停止
W25Q64_CS_H;
//判断空闲
if(temp & (0x01))
{
return 1;
}
return 0;
}
3、擦除函数(除了全部擦除函数的代码步骤不同以外,其他擦除的代码步骤相同,这里使用了传入指定的指令来执行对应的擦除功能)


/*************************
函数名称:w25_Erase(void)
函数功能:w25擦除函数
返回值:无
形参:u32 addr,cmd : 擦除指令 (0x20=扇区, 0xD8=块, 0xC7=整片)
作者:me
版本:1.0
*************************/
void w25_Sector_Erase(u32 addr,u8 cmd)
{
//写 WEL位 0 是 芯片拒绝执行任何写入、擦除或写状态寄存器的指令。且与写使能是绑定的所有一开始就要写使能
w25_Wr_Enable();
while(w25_Re_Free());//等待空闲
W25Q64_CS_L;
//发送擦除指令
Spi1_Change_By(cmd);
if(cmd != 0xc7)
{
Spi1_Change_By((addr >> 16) & 0xff);
Spi1_Change_By((addr >> 8) & 0xff);
Spi1_Change_By(addr & 0xff);
}
//拉高
W25Q64_CS_H;
while(w25_Re_Free());//等待扇区擦除完成
}
4、页写函数

/*************************
函数名称:w25_Wr_Pg(u8 *data,u32 addr,u32 len)
函数功能:w25页写函数
返回值:无
形参:u8 *data,u32 addr,u32 len
作者:me
版本:1.0
*************************/
void w25_Wr_Pg(u32 addr,u8 *data,u32 len)
{
w25_Wr_Enable();
while(w25_Re_Free());//等待空闲
W25Q64_CS_L;
//发送擦除指令
Spi1_Change_By(0x02);
//发送写入地址
Spi1_Change_By((addr >> 16) & 0xff);
Spi1_Change_By((addr >> 8) & 0xff);
Spi1_Change_By(addr & 0xff);
while(len -- )
{
Spi1_Change_By(*data);
data++;
}
//拉高
W25Q64_CS_H;
while(w25_Re_Free());//等待空闲
}
5、页读

/*************************
函数名称:w25_Re_Pg(u8 *data,u32 addr,u32 len)
函数功能:w25页读函数
返回值:无
形参:无
作者:me
版本:1.0
*************************/
void w25_Re_Pg(u32 addr,u8 *data,u32 len)
{
W25Q64_CS_L;
//发送擦除指令
Spi1_Change_By(0x03);
//发送写入地址
Spi1_Change_By((addr >> 16) & 0xff);
Spi1_Change_By((addr >> 8) & 0xff);
Spi1_Change_By(addr & 0xff);
while(len --)
{
*data = Spi1_Change_By(0xff);
data++;//地址偏移
}
//拉高
W25Q64_CS_H;
}
6、跨页写
原理与AT24C02相同,通过判断要写入数据的长度从而改变真实写入的长度,
再利用这个长度移动,写入地址,数据地址,数据长度
/*************************
函数名称:w25_Wr_Ct(u8 *data,u32 addr,u32 len)
函数功能:w25跨页写函数
返回值:无
形参:u8 *data,u32 addr,u32 len
作者:me
版本:1.0
*************************/
void w25_Wr_Ct(u32 addr,u8 *data,u32 len)
{
u32 Re_Wr;
u32 Max_Space;
while(len)
{
Max_Space = 256 - (addr % 256);
if(Max_Space > len)
{
Re_Wr = len;
}
else
{
Re_Wr = Max_Space;
}
w25_Wr_Enable();
while(w25_Re_Free());//等待空闲
W25Q64_CS_L;
//发送擦除指令
Spi1_Change_By(0x02);
//发送写入地址
Spi1_Change_By((addr >> 16) & 0xff);
Spi1_Change_By((addr >> 8) & 0xff);
Spi1_Change_By(addr & 0xff);
for(u32 i=0;i<Re_Wr;i++)
{
Spi1_Change_By(data[i]);
}
//拉高
W25Q64_CS_H;
while(w25_Re_Free());//等待空闲
addr += Re_Wr;
data += Re_Wr;
len -= Re_Wr;
}
}
更多推荐


所有评论(0)