STM32F103标准库开发----目录
STM32F103标准库开发----SPI实验----基本原理
STM32F103标准库开发----SPI实验----底层驱动程序
W25Qxx全系列----数据手册
W25Qxx 系列 Flash 存储器可以为用户提供存储解决方案。擦写周期多达10W次,可将数据保存达20年之久,支持2.7~3.6V的电压,支持标准的SPI,还支持双输出/四输出的SPI,最大SPI时钟可达80Mhz。
W25Qxx 系列 Flash 存储器是为系统提供一个最小空间、最少引脚,最低功耗的串行Flash存储器,比普通的串行Flash存储器更灵活,性能更优越。
功耗低,正常工作状态下电流消耗0.5mA,掉电状态下电流消耗1uA。
W25Qxx 系列 Flash 存储器的存储结构
相同点:
不同点: 容量和内存空间地址不同,具体如下表所示:
芯片型号 | 总容量 | 总块数 | 内存空间地址 |
---|---|---|---|
W25Q80 | 8M(bit)—1M(字节) | 16 | 0x000000~0x0FFFFF(24bit) |
W25Q16 | 16M(bit)—2M(字节) | 32 | 0x000000~0x1FFFFF(24bit) |
W25Q32 | 32M(bit)—4M(字节) | 64 | 0x000000~0x3FFFFF(24bit) |
W25Q64 | 64M(bit)—8M(字节) | 128 | 0x000000~0x7FFFFF(24bit) |
W25Q128 | 128M(bit)—16M(字节) | 256 | 0x000000~0xFFFFFF(24bit) |
W25Q256 | 256M(bit)—32M(字节) | 512 | 0x00000000~0x01FFFFFF(32bit) |
W25Q512 | 512M(bit)—64M(字节) | 1024 | 0x00000000~0x03FFFFFF(32bit) |
片选引脚:/CS
(1)当CS引脚为高电平时,芯片被禁能,DO引脚高阻态,不能进行读写操作。
(2)当CS引脚为低电平时,芯片被使能,能进行读写操作。
上电后,执行一条新指令之前必须使CS引脚先有一个下降沿。
数据输出引脚:DO(IO1)
标准SPI模式: CLK上升沿捕获地址和命令,下降沿输出数据。
QSPI模式: 双向数据传输 IO1。
写保护引脚:/WP(IO2)
标准SPI模式:
写保护引脚可以被用来保护状态寄存器不被意外改写。
(1)当WP引脚为高电平时,芯片写保护失能,可以正常写入数据。
(2)当WP引脚为低电平时,芯片写保护使能,不可以正常写入数据。
QSPI模式: 双向数据传输 IO2。
地:GND
电源地
数据输入引脚:DI(IO0)
标准SPI模式:
数据、地址和命令从DI引脚送到芯片内部,在CLK引脚的上升沿捕获。
QSPI模式: 双向数据传输 IO0。
串行时钟引脚:CLK
SPI时钟引脚,为输入输出提供时序。
保持引脚:/HOLD(IO3)
标准SPI模式:
当CS引脚为低电平时
(1)当HOLD为低电平时,DO引脚处于高阻态状态,而且也会忽略DIO和CLK引脚上的信号。
(2)当HOLD为高电平时,芯片恢复正常工作。
QSPI模式: 双向数据传输 IO3。
电源:VCC
电源正极
W25Qxx 系列 Flash 存储器支持 JEDEC 标准,具有唯一的 64 位识别序列号,方便区别芯片型号,具体如下表所示:
芯片型号 | 芯片ID(64bit) |
---|---|
W25Q80 | 0xEF13 |
W25Q16 | 0xEF14 |
W25Q32 | 0xEF15 |
W25Q64 | 0xEF16 |
W25Q128 | 0xEF17 |
W25Q256 | 0xEF18 |
W25Q512 | 0xEF19 |
W25Qxx系列芯片支持以下两种SPI通信方式:
模式0: CPOL = 0,CPHA = 0
模式3: CPOL = 1,CPHA = 1
注:这里是记录所有W25Qxx系列芯片的状态寄存器,有些型号的状态寄存器,没有全部功能。
S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 |
---|---|---|---|---|---|---|---|
SRP | SEC | TB | BP2 | BP1 | BP0 | WEL | BUSY |
读/写 | 读/写 | 读/写 | 读/写 | 读/写 | 读/写 | 只读 | 只读 |
S0----总线忙标志位(BUSY)
在执行页编程、扇区擦除、块区擦除、芯片擦除以及写状态寄存器指令时,该位被硬件自动置1。这时候,除了读状态寄存器指令外的所有操作指令都会被芯片忽略。
当芯片执行完这些指令后,硬件会自动将该位清0,表示芯片器件可以接收其他的指令。
S1----写保护位(WEL)
执行完写使能指令后,该位置1
当芯片掉电后和执行写禁能、页编程、扇区擦除、块区擦除以及芯片擦除指令都会进入写保护状态,该位置0
S2、S3、S4----块区保护位(BP2、BP1、BP0)
这3个位默认状态为0,即块区处于未保护状态。可以利用“写状态寄存器”指令对这几个位进行置1来达到块区保护的目的。块区保护状态为:没有保护、部分保护和全部保护状态。
当状态寄存器的SRP位为1或读写保护管脚(/WP)为低电平时,这3个位不可被更改。
S5----底部和顶部块保护位(TB)
此位默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。
当TB = 0时,表示保护位从顶部开始;
当TB = 1时,表示保护位从底部开始。
当状态寄存器的SRP位为1或读写保护管脚(/WP)为低电平时,这个位不可被更改。
S6----扇区/块保护(SEC)
此位默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。
当SEC = 0时,表示每次保护的区域大小为4K;
当SEC = 1时,表示每次保护的区域大小为64K。
S15 | S14 | S13 | S12 | S11 | S10 | S9 | S8 |
---|---|---|---|---|---|---|---|
SUS | CMP | LB3 | LB2 | LB1 | 预留 | QE | SRL |
只读 | 读/写 | 读/写 | 读/写 | 读/写 | 无 | 读/写 | 读/写 |
S7、S8----状态寄存器保护位(SRP、SRL)
这两个位的默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。
这两位和读写保护管脚(/WP)决定了状态寄存器写保护的方式。
状态寄存器写保护的方式有:软件保护,硬件保护、电源锁定或一次性可编程(OTP)保护。
S9----快速SPI通讯使能(QE)
此位默认值为0,可以利用“写状态寄存器”指令对这个位进行置1或清零。
当QE = 0时,设置为标准速度模式或快速模式,保持管脚(/HOLE)和读写保护管脚(/WP)启用;
当QE = 1时,设置为高速模式,保持管脚(/HOLE)和读写保护管脚(/WP)被设置为IO2和IO3功能使用。
S10、S11、S12、S13----安全寄存器锁位(LB3、LB2、LB1)
LB3-1的默认状态为0,安全寄存器被解锁。
可以使用写状态寄存器指令将LB3-1单独设置为1。
LB3-1是一次性可编程(OTP),一旦它设置为1,相应的256字节安全寄存器将成为永久只读。
S14----补码保护位(CMP)
它与SEC、TB、BP2、BP1和BP0位结合使用,为阵列保护提供更大的灵活性。
一旦CMP设置为1,之前SEC、TB、BP2、BP1和BP0设置的阵列保护将被逆转。例如:
当CMP=0时,一个最高64KB的块可以被保护,而数组的其他部分则不受保护;
当CMP=1时,最上面的64KB块将成为不受保护的,而数组的其余部分将成为只读的。
默认设置为CMP=0。
S15----暂停状态位(SUS)
在执行**擦除/程序暂停(75h)指令后设置为1。
通过擦除/程序恢复 (7Ah)**指令以及下电、上电周期将SUS状态位清除为0。
S23 | S22 | S21 | S20 | S19 | S18 | S17 | S16 |
---|---|---|---|---|---|---|---|
HOLD/RST | DRV1 | DRV0 | 预留 | 预留 | WPS | ADP | ADS |
读/写 | 读/写 | 读/写 | 无 | 无 | 读/写 | 读/写 | 只读 |
S16----当前地址模式(ADS)
表示设备当前运行的地址模式。
当ADS=0时,设备处于3字节地址模式,
当ADS=1时,设备处于4字节地址模式。
S17----启动时地址模式(ADP)
决定设备上电或复位时的初始地址模式,该位仅在上电或设备复位初始化期间使用。
当ADP=0(出厂默认)时,设备将启动到3字节地址模式,扩展地址寄存器必须用于访问超过128Mb的内存区域。当ADP=1时,设备将直接启动到4字节地址模式。
S18----写保护方案(WPS)
当WPS=0时,设备将使用CMP、SEC、TB、BP[2:0]位的组合来保护存储阵列的特定区域。
当WPS=1时,设备将使用单独块锁来保护任何单独的扇区或块。
设备上电或复位后,所有单个块锁定位的缺省值为1。
S22、S21 ---- 输出信号强度(DRV1、DRV0)
S23----HOLD/RST引脚功能选择
当HOLD/RST=0(出厂设置)时,引脚为/HOLD。
当HOLD/RST=1时,引脚为/RESET。
但是,只有当QE=0时,/HOLD或/RESET函数才可用。
QE设置为1时,关闭/HOLD和/RESET功能,引脚为专用数据I/O引脚。
单字节操作,只往芯片中写入1字节的操作命令,具体代码如下:
void W25QXX_Write_Enable(void) //写使能
{
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0x06); //写入1字节操作命令
W25QXX_CS(1); //拉高片选CS引脚---关闭芯片
}
操作命令 如下表所示:
指令名称 | 指令数据(hex) | 功能 |
---|---|---|
Write Enable | 0x06 | 写操作启用 |
Volatile SR Write Enable | 0x50 | 易失性状态寄存器的写启用 |
Write Disable | 0x04 | 写操作禁用 |
Set Read Parameters | 0xC0 | 设置读取参数 |
Chip Erase | 0xC7/0x60 | 擦除芯片 |
Global Block/Sector Lock | 0x7E | 全局块/扇区上锁 |
Global Block/Sector Unlock | 0x98 | 全局块/扇区解锁 |
Erase / Program Suspend | 0x75 | 擦除/程序挂起 |
Erase / Program Resume | 0x7A | 擦除/程序恢复 |
Power-down | 0xB9 | 断电 |
Release Power-down | 0xAB | 解除断电 |
Enter 4-Byte Address Mode | 0xB7 | 输入4字节地址模式 |
Exit 4-Byte Address Mode | 0xE9 | 退出4字节地址模式 |
Enter QPI Mode | 0x38 | 开启QSPI模式 |
Exit QPI Mode | 0xFF | 退出QSPI模式 |
Enable Reset | 0x66 | 使能复位 |
Reset Device | 0x99 | 复位 |
注:如果想要实现其他功能,替换操作指令数据,便可实现功能。
双字节操作,先往芯片中写入1字节的操作命令,接下来是读取/写入的字节数据。
具体代码如下:
//读取1字节数据
uint8_t W25QXX_ReadSR(void)//读取状态寄存器
{
uint8_t data=0;
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0x05); //写入1字节操作命令
data=W25QXX_ReadWriteByte(0Xff); //读取1字节数据
W25QXX_CS(1); //拉高片选CS引脚---取消片选
return data;
}
//写入1字节数据
void W25QXX_WriteSR(uint8_t data)//写状态寄存器
{
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0x01); //写入1字节操作命令
W25QXX_ReadWriteByte(data); //写入1字节数据
W25QXX_CS(1); //拉高片选CS引脚---取消片选
}
操作命令 如下表所示:
指令名称 | 指令数据(hex) | 写入/读取的数据(hex) | 功能 |
---|---|---|---|
Read Status Register-1 | 0x05 | (S7-S0) | 读状态寄存器1 |
Write Status Register-1 | 0x01 | (S7-S0) | 写状态寄存器1 |
Read Status Register-2 | 0x35 | (S15-S8) | 读状态寄存器2 |
Write Status Register-2 | 0x31 | (S15-S8) | 写状态寄存器2 |
Read Status Register-3 | 0x15 | (S23-S16) | 读状态寄存器3 |
Write Status Register-3 | 0x11 | (S23-S16) | 写状态寄存器3 |
Read Extended Addr. Reg | 0xC8 | (EA7-EA0) | 读扩展地址寄存器 |
Write Extended Addr. Reg | 0xC5 | (EA7-EA0) | 写扩展地址寄存器 |
注:如果想要实现其他功能,替换操作指令数据,便可实现功能。
具体代码如下:
uint16_t W25QXX_ReadID(void)//读取芯片ID
{
uint16_t ID = 0;
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0x90); //发送读取ID命令
W25QXX_ReadWriteByte(0x00);
W25QXX_ReadWriteByte(0x00);
W25QXX_ReadWriteByte(0x00);
ID|=W25QXX_ReadWriteByte(0xFF)<<8;
ID|=W25QXX_ReadWriteByte(0xFF);
W25QXX_CS(1); //拉高片选CS引脚---取消片选
return ID;
}
操作命令 如下表所示:
指令名称 | 指令数据(hex) | 字节1 | 字节2 | 字节3 | 字节4 | 字节5 | 功能 |
---|---|---|---|---|---|---|---|
Device ID | 0xAB | 0x00 | 0x00 | 0x00 | (ID7-ID0) | 读取设备ID | |
Manufacturer/Device ID | 0x90 | 0x00 | 0x00 | 0x00 | (MF7-MF0) | (ID7-ID0) | 读取制造商+设备ID |
JEDEC ID | 0x9F | (MF7-MF0) | (ID15-ID8) | (ID7-ID0) | 读取全部ID | ||
Read Unique ID | 0x4B | 0x00 | 0x00 | 0x00 | 0x00 | (UID63-0) | 读取唯一ID号 |
注:如果想要实现其他功能,替换操作指令数据,便可实现功能。
带地址操作主要分两种:
3字节地址:W25Qxx系列芯片都可以使用。
4字节地址:只有W25Q256和W25Q512可用。
//读取数据
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0x03); //发送读取命令
W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>16)); //发送24bit地址
W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>8));
W25QXX_ReadWriteByte((uint8_t)ReadAddr);
for(uint16_t i=0;i<NumByteToRead;i++)//可读多个数据
{
pBuffer[i]=W25QXX_ReadWriteByte(0XFF); //循环读数
}
W25QXX_CS(1);
}
//写入数据
void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
W25QXX_Write_Enable(); //写使能
W25QXX_CS(0); //使能器件
W25QXX_ReadWriteByte(0x02); //发送页写命令
W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址
W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>8));
W25QXX_ReadWriteByte((uint8_t)WriteAddr);
for(uint16_t i=0;i<NumByteToWrite;i++)//可写多个数据,最多256个字节一页数据
{
W25QXX_ReadWriteByte(pBuffer[i]);//循环写数
}
W25QXX_CS(1); //取消片选
W25QXX_Wait_Busy(); //等待写入结束
}
操作命令 如下表所示:
指令名称 | 指令数据(hex) | 地址1 | 地址2 | 地址3 | 数据1 | 数据2 | 功能 |
---|---|---|---|---|---|---|---|
Read Data | 0x03 | A23-A16 | A15-A8 | A7-A0 | (D7-D0) | (D7-D0) | 读取数据 |
Fast Read | 0x0B | A23-A16 | A15-A8 | A7-A0 | 0x00 | (D7-D0) | 快速读取数据 |
Page Program | 0x02 | A23-A16 | A15-A8 | A7-A0 | (D7-D0) | (D7-D0) | 页写数据 |
Sector Erase (4KB) | 0x20 | A23-A16 | A15-A8 | A7-A0 | 扇区擦除 | ||
Block Erase (32KB) | 0x52 | A23-A16 | A15-A8 | A7-A0 | 半块擦除 | ||
Block Erase (64KB) | 0xD8 | A23-A16 | A15-A8 | A7-A0 | 整块擦除 | ||
Read SFDP Register | 0x5A | A23-A16 | A15-A8 | A7-A0 | 0x00 | (D7-D0) | |
Erase Security Register | 0x44 | A23-A16 | A15-A8 | A7-A0 | 擦除安全寄存器 | ||
Program Security Register | 0x42 | A23-A16 | A15-A8 | A7-A0 | (D7-D0) | (D7-D0) | 编辑安全寄存器 |
Read Security Register | 0x48 | A23-A16 | A15-A8 | A7-A0 | 0x00 | (D7-D0) | 读取安全寄存器 |
Erase Security Register | 0x3D | A23-A16 | A15-A8 | A7-A0 | (L7-L0) | 读块锁 | |
Individual Block Lock | 0x36 | A23-A16 | A15-A8 | A7-A0 | 单块上锁 | ||
Individual Block Unlock | 0x39 | A23-A16 | A15-A8 | A7-A0 | 单块解锁 |
//启用4字节地址模式
void W25QXX_Enter_4Byte()
{
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0xB7); //写入1字节操作命令
W25QXX_CS(1); //拉高片选CS引脚---关闭芯片
}
//退出4字节地址模式
void W25QXX_Exit_4Byte()
{
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0xE9); //写入1字节操作命令
W25QXX_CS(1); //拉高片选CS引脚---关闭芯片
}
//读取数据
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
{
W25QXX_CS(0); //拉低片选CS引脚---使能芯片
W25QXX_ReadWriteByte(0x13); //发送4字节地址读取命令
W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>24));//发送32bit地址
W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>16));
W25QXX_ReadWriteByte((uint8_t)((ReadAddr)>>8));
W25QXX_ReadWriteByte((uint8_t)ReadAddr);
for(uint16_t i=0;i<NumByteToRead;i++)//可读多个数据
{
pBuffer[i]=W25QXX_ReadWriteByte(0XFF); //循环读数
}
W25QXX_CS(1);
}
//写入数据
void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
{
W25QXX_Write_Enable(); //写使能
W25QXX_CS(0); //使能器件
W25QXX_ReadWriteByte(0x12); //发送4字节地址页写命令
W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>24));//发送32bit地址
W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>16));
W25QXX_ReadWriteByte((uint8_t)((WriteAddr)>>8));
W25QXX_ReadWriteByte((uint8_t)WriteAddr);
for(uint16_t i=0;i<NumByteToWrite;i++)//可写多个数据,最多256个字节一页数据
{
W25QXX_ReadWriteByte(pBuffer[i]);//循环写数
}
W25QXX_CS(1); //取消片选
W25QXX_Wait_Busy(); //等待写入结束
}
注:如果想要实现4字节地址,需要启用4字节地址模式。
操作命令 如下表所示:
指令名称 | 指令数据(hex) | 地址1 | 地址2 | 地址3 | 地址4 | 数据1 | 数据2 | 功能 |
---|---|---|---|---|---|---|---|---|
Read Data with 4-Byte Address | 0x13 | A31-A24 | A23-A16 | A15-A8 | A7-A0 | (D7-D0) | (D7-D0) | 读取4字节地址数据 |
Fast Read with 4-Byte Address | 0x0B | A31-A24 | A23-A16 | A15-A8 | A7-A0 | 0x00 | (D7-D0) | 快读4字节地址数据 |
Page Program with 4-Byte Address | 0x12 | A31-A24 | A23-A16 | A15-A8 | A7-A0 | (D7-D0) | (D7-D0) | 页写4字节地址数据 |
Sector Erase (4KB) with 4-Byte Address | 0x21 | A31-A24 | A23-A16 | A15-A8 | A7-A0 | 扇区擦除4字节地址数据 | ||
Block Erase (64KB) with 4-Byte Address | 0xDC | A31-A24 | A23-A16 | A15-A8 | A7-A0 | 整块擦除4字节地址数据 |