本篇指南仅用作W25Qxx系列初级学习使用,是本人在学习过程中的一个自我记录,不用做商业用途。代码多参考自正点原子例程,无本人版权。在本篇文档中如有部分不详尽的地方,欢迎评论留言,或联系本人邮箱syujen_1997@163.com。
W25Q64存储容量共64M-bit/ 8M-byte,32768页(pages)、每页256-bytes。最大一次可编程256-bytes。W25Q128JV存储容量共128M-bit/ 16M-byte
一次擦除大小可以为16页(4KB)、128页(32KB)、256页(64KB)或者全擦除。
W25Q64JV有2048个可擦除扇区(sectors),或者可以说有128个可擦除块(blocks)。关系 1 Block = 16 sectors;1 sector = 4KB,所以算起来能达到8M-byte。
编程即写数据,由于Flash的特性,只能从1编程0,所以写数据之前Flash里面的数据不是0xFF就必须先擦除,然后才能写数据。擦除即将Flash里面的数据恢复为0xFF的过程。
上电后设备自动处于写禁用状态(Write Enable Latch, WEL为0,WEL是只读位)。在Page Program, Sector Erase, Block Erase, Chip Erase or Write Status Register instruction(页编程、区擦除、块擦除、芯片擦除或者写状态寄存器指令)之前必须先进行写使能指令。在编程、擦除、写状态寄存器指令完成后,WEL自动变成0。
BUSY位是状态寄存器0的第0位,并且是只读位。当执行页编程、区擦除、块擦除、芯片擦除、写状态寄存器、擦除/编程安全寄存器指令时,其值为1,并且在此期间不再接收新的指令,但是可以接收读状态寄存器指令和擦除编程挂起指令。
W25Q128JV系列存储器框图
这里仅给出W25Q128JV系列存储器框图,其余系列需查看其对应手册。
再次重申,1 Block = 16 sectors;1 sector = 4KB。从图中可以看出,Block 0 的 Sector 0寻址范围是 0x000000到0x000FFF,会发现是0x000FFF=2^12-1 = 4095,正好是4KB(4 * 1024 bytes,地址加1的单位是字节,不是bit)
标准SPI通讯下支持SPI总线操作模式为0(0,0)和3(1,1)。通常采用模式3(即CPOL=1, CPHA=1,SCK引脚在空闲状态下处于高电平,SCK引脚上的第二个边沿对MSBit采样)。Dual SPI、Quad SPI在此不深入讨论。
需要注意的是,W25Qxx系列对SPI的通讯时钟是有限制的,最大为133M,配置stm32时需注意。
翻译:该指令通过将 /CS 引脚驱动为低电平并移位指令代码“90h”后跟 24 位地址 (A23-A0) 000000h 来启动。之后,Winbond 的制造商 ID (EFh) 和设备 ID 在CLK的下降沿移出,最高有效位 (MSB) 在前,如图39所示。
也就是说,采取方法1的情况下,向W25Q128发送
该指令通过将 /CS 引脚拉低并移位指令代码“9Fh”来启动。
5 操作W25Qxx的一些基础操作
读取数据指令允许从存储器中顺序读取一个或多个数据字节。通过将 /CS 引脚驱动为低电平来启动指令,然后将指令代码“03h”和一个 24 位地址 (A23-A0) 移入DI引脚。代码和地址位在CLK引脚的上升沿锁存。接收到地址后,寻址存储器位置的数据字节将在CLK的下降沿移出DO引脚,最高有效位(MSB)在前。在移出每个数据字节后,地址会自动递增到下一个更高的地址,从而实现连续的数据流。这意味着只要时钟继续,就可以用一条指令访问整个内存。该指令通过驱动 /CS 为高电平来完成。
读数据指令序列如图14所示。如果在擦除、编程或写周期正在进行(BUSY=1)时发出读数据指令,该指令将被忽略并且不会有任何对当前周期的影响。
读取数据 (03h) 指令仅在标准 SPI 模式下受支持。
需注意的是,W25Q256系列应发送地址为4字节(即32-bit)
写启用指令(图5)将状态寄存器中的写启用闩锁(WEL)位设置为1。WEL位必须在每个页面程序、四页程序、扇区擦除、块擦除、芯片擦除、写入状态寄存器和擦除/程序安全寄存器指令之前设置。写入启用指令是通过驱动/CS低位,将指令代码“06h”移动到CLK上升沿上的数据输入(DI)引脚,然后驱动/CS高位来输入的。
读取状态寄存器指令允许读取8位状态寄存器。通过将/CS驱动为低电平并将状态寄存器1的指令代码“05h”、状态寄存器2的指令代码“35h”或状态寄存器 3的指令代码“15h”在CLK的上升沿移入DI引脚来输入指令。然后状态寄存器位在CLK的下降沿移出 DO 引脚,最高有效位 (MSB) 在前,如图 8 所示。有关状态寄存器的说明,请参阅第7.1节。
读取状态寄存器指令可以在任何时候使用,即使是在编程、擦除或写入状态寄存器周期正在进行时。这允许检查BUSY状态位以确定周期何时完成以及设备是否可以接受另一条指令。可以连续读取状态寄存器,如图8所示。该指令通过驱动/CS为高电平来完成。
BUSY — 当设备执行页面程序、四页程序、扇区擦除、块擦除、芯片擦除、写入状态寄存器或擦除/程序安全寄存器指令时,该位被设置为1状态。当程序、擦除或写入状态/安全寄存器指令完成时,忙碌位将被清除为0状态,表明设备已准备好接受进一步指令。
需注意的是W25Q256的状态寄存器3最低位与其它W25Qxx系列不同。
ADS — 当前地址模式位是状态寄存器-3中的只读位,指示设备当前运行的地址模式。当ADS=0时,设备处于3字节地址模式,当ADS=1时,设备处于4字节地址模式。
扇区擦除指令将指定扇区(4K 字节)内的所有存储器设置为全 1 (FFh) 的擦除状态。在设备接受扇区擦除指令之前必须执行写使能指令(状态寄存器位 WEL 必须等于 1)。该指令通过将 /CS 引脚驱动为低电平并将指令代码“20h”移动到 24 位扇区地址 (A23-A0) 来启动。扇区擦除指令序列如图 31a 所示。
在最后一个字节的第 8 位被锁存后,/CS 引脚必须被驱动为高电平。如果不这样做,则不会执行扇区擦除指令。 /CS 被驱动为高电平后,自定时扇区擦除指令将开始持续 tSE 时间(参见 AC 特性)。当扇区擦除周期正在进行时,仍可以访问读取状态寄存器指令以检查 BUSY 位的状态。 BUSY 位在扇区擦除周期内为 1,当周期结束且器件准备好再次接受其他指令时变为 0。扇区擦除周期完成后,状态寄存器中的写使能锁存器 (WEL) 位清零。如果寻址页受到块保护(CMP、SEC、TB、BP2)的保护,则不会执行扇区擦除指令、BP1 和 BP0) 位或单个块/扇区锁定。
写操作较为复杂,主要是因为写之前要擦除、最大一次性只能写256 Byte(即一个完整的page,硬件不会自动换page,所以要编程)所以要考虑换页、写操作给的指令中的起始地址再某一页的哪个位置等等
页编程指令允许在先前已擦除(FFh)的存储器位置对1个字节到256个字节(一页)的数据进行编程。在设备接受页编程指令(状态寄存器位 WEL= 1)之前,必须执行写使能指令。该指令通过将/CS引脚驱动为低电平,然后将指令代码“02h”、后跟 24 位地址(A23-A0)和至少一个数据字节移入DI引脚来启动。在向器件发送数据时,/CS引脚必须在整个指令长度内保持低电平。
如果要对整个256字节页面进行编程,则最后一个地址字节(8 个最低有效地址位)应设置为0。如果最后一个地址字节不为零,并且时钟数超过剩余页面长度,则寻址将换行到页面的开头。在某些情况下,可以对少于256个字节(部分页面)进行编程,而不会对同一页面中的其他字节产生任何影响。执行部分页面编程的一个条件是时钟数不能超过剩余页面长度。如果发送到设备的字节数超过256个,则寻址将换行到页面的开头并覆蓋先前发送的数据。
与写入和擦除指令一样,在最后一个字节的第 8 位被锁存后,/CS引脚必须被驱动为高电平。如果不这样做,页面编程指令将不会被执行。在/CS被驱动为高电平后,自定时页面编程指令将开始持续 tpp 时间(参见AC特性)。在页面编程周期正在进行时,仍可以访问读取状态寄存器指令以检查 BUSY 位的状态。BUSY位在页编程周期内为1,当周期结束且器件准备好再次接受其他指令时变为0。页面编程周期完成后,状态寄存器中的写使能锁存器 (WEL) 位被清零。如果寻址页面受到块保护(CMP、SEC、TB、BP2)的保护,则不会执行页面编程指令、BP1和BP0)位或单个块/扇区锁定。
为了完成写操作,共定义了3个函数,“页面写操作(限定小于256 byte)”、“带换页的写操作(没有进行擦除操作)”,以及给用户直接调用的“写操作(带擦除)”。代码较为复杂,这里大致介绍一下思路:
不得不说,原子哥写程序的逻辑是有点儿绕 2333