基本信息
- W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器
- 常用于数据存储、字库存储、固件程序存储等场景
- 存储介质:Nor Flash(闪存)
- 时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)
存储容量(24位地址)
| 型号 | 容量(bit) | 容量(Byte) |
|---|---|---|
| W25Q40 | 4Mbit | 512KByte |
| W25Q80 | 8Mbit | 1MByte |
| W25Q16 | 16Mbit | 2MByte |
| W25Q32 | 32Mbit | 4MByte |
| W25Q64 | 64Mbit | 8MByte |
| W25Q128 | 128Mbit | 16MByte |
| W25Q256 | 256Mbit | 32MByte |
W21Q64使用步骤
软件SPI操作步骤
| 步骤 | 操作 | 函数调用 | 参数说明 |
|---|---|---|---|
| 1 | 初始化软件SPI | SoftSPI_Init() | 无参数 |
| 2 | 初始化W25Q64 | W25Q64_Init() | 无参数 |
| 3 | 读取数据 | W25Q64_ReadData(Address, DataArray, Count) | Address: 读取起始地址 DataArray: 存储读取数据的缓冲区 Count: 要读取的字节数 |
| 4 | 擦除扇区 | W25Q64_SectorErase(Address) | Address: 要擦除的扇区地址 |
| 5 | 写入数据 | W25Q64_PageProgram(Address, DataArray, Count) | Address: 写入起始地址 DataArray: 要写入的数据缓冲区 Count: 要写入的字节数(最大256字节) |
| 6 | 读取JEDEC ID | W25Q64_ReadJEDECID() | 无参数,返回32位JEDEC ID |
硬件SPI操作步骤
| 步骤 | 操作 | 函数调用 | 参数说明 |
|---|---|---|---|
| 1 | 初始化硬件SPI | HardSPI_Init() | 无参数 |
| 2 | 初始化W25Q64 | W25Q64_HardInit() | 无参数 |
| 3 | 读取数据 | W25Q64_HardReadData(Address, DataArray, Count) | Address: 读取起始地址 DataArray: 存储读取数据的缓冲区 Count: 要读取的字节数 |
| 4 | 擦除扇区 | W25Q64_HardSectorErase(Address) | Address: 要擦除的扇区地址 |
| 5 | 写入数据 | W25Q64_HardPageProgram(Address, DataArray, Count) | Address: 写入起始地址 DataArray: 要写入的数据缓冲区 Count: 要写入的字节数(最大256字节) |
| 6 | 读取JEDEC ID | W25Q64_HardReadJEDECID() | 无参数,返回32位JEDEC ID |
软件SPI示例
c
void W25Q64_SoftwareExample(void)
{
uint8_t readBuffer[10];
uint8_t writeBuffer[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
uint32_t jedecID;
// 初始化
SoftSPI_Init();
W25Q64_Init();
// 读取JEDEC ID
jedecID = W25Q64_ReadJEDECID();
// 擦除扇区
W25Q64_SectorErase(0x000000);
// 写入数据
W25Q64_PageProgram(0x000000, writeBuffer, 5);
// 读取数据
W25Q64_ReadData(0x000000, readBuffer, 5);
}硬件SPI示例
c
void W25Q64_HardwareExample(void)
{
uint8_t readBuffer[10];
uint8_t writeBuffer[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
uint32_t jedecID;
// 初始化
HardSPI_Init();
W25Q64_HardInit();
// 读取JEDEC ID
jedecID = W25Q64_HardReadJEDECID();
// 擦除扇区
W25Q64_HardSectorErase(0x000000);
// 写入数据
W25Q64_HardPageProgram(0x000000, writeBuffer, 5);
// 读取数据
W25Q64_HardReadData(0x000000, readBuffer, 5);
}配置代码
// 写使能
void W25Q64_WriteEnable(void)
{
SoftSPI_W_SS(0);
SoftSPI_Transfer(W25Q64_CMD_WRITE_ENABLE);
SoftSPI_W_SS(1);
}
// 等待忙状态结束
void W25Q64_WaitBusy(void)
{
uint8_t Status;
SoftSPI_W_SS(0);
SoftSPI_Transfer(W25Q64_CMD_READ_STATUS_REG1);
do
{
Status = SoftSPI_Transfer(0xFF);
} while (Status & 0x01);
SoftSPI_W_SS(1);
}
// 页编程
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{
W25Q64_WriteEnable();
W25Q64_WaitBusy();
SoftSPI_W_SS(0);
SoftSPI_Transfer(W25Q64_CMD_PAGE_PROGRAM);
SoftSPI_Transfer((Address >> 16) & 0xFF);
SoftSPI_Transfer((Address >> 8) & 0xFF);
SoftSPI_Transfer(Address & 0xFF);
while (Count--)
{
SoftSPI_Transfer(*DataArray++);
}
SoftSPI_W_SS(1);
W25Q64_WaitBusy();
}
// 扇区擦除
void W25Q64_SectorErase(uint32_t Address)
{
W25Q64_WriteEnable();
W25Q64_WaitBusy();
SoftSPI_W_SS(0);
SoftSPI_Transfer(W25Q64_CMD_SECTOR_ERASE_4KB);
SoftSPI_Transfer((Address >> 16) & 0xFF);
SoftSPI_Transfer((Address >> 8) & 0xFF);
SoftSPI_Transfer(Address & 0xFF);
SoftSPI_W_SS(1);
W25Q64_WaitBusy();
}
// 读取数据
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{
W25Q64_WaitBusy();
SoftSPI_W_SS(0);
SoftSPI_Transfer(W25Q64_CMD_READ_DATA);
SoftSPI_Transfer((Address >> 16) & 0xFF);
SoftSPI_Transfer((Address >> 8) & 0xFF);
SoftSPI_Transfer(Address & 0xFF);
while (Count--)
{
*DataArray++ = SoftSPI_Transfer(0xFF);
}
SoftSPI_W_SS(1);
}
// 读取JEDEC ID
uint32_t W25Q64_ReadJEDECID(void)
{
uint32_t JEDECID = 0;
SoftSPI_W_SS(0);
SoftSPI_Transfer(W25Q64_CMD_JEDEC_ID);
JEDECID |= (uint32_t)SoftSPI_Transfer(0xFF) << 16;
JEDECID |= (uint32_t)SoftSPI_Transfer(0xFF) << 8;
JEDECID |= SoftSPI_Transfer(0xFF);
SoftSPI_W_SS(1);
return JEDECID;
}
// 硬件SPI写使能
void W25Q64_HardWriteEnable(void)
{
HardSPI_W_SS(0);
HardSPI_Transfer(W25Q64_CMD_WRITE_ENABLE);
HardSPI_W_SS(1);
}
// 硬件SPI等待忙状态结束
void W25Q64_HardWaitBusy(void)
{
uint8_t Status;
HardSPI_W_SS(0);
HardSPI_Transfer(W25Q64_CMD_READ_STATUS_REG1);
do
{
Status = HardSPI_Transfer(0xFF);
} while (Status & 0x01);
HardSPI_W_SS(1);
}
// 硬件SPI页编程
void W25Q64_HardPageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{
W25Q64_HardWriteEnable();
W25Q64_HardWaitBusy();
HardSPI_W_SS(0);
HardSPI_Transfer(W25Q64_CMD_PAGE_PROGRAM);
HardSPI_Transfer((Address >> 16) & 0xFF);
HardSPI_Transfer((Address >> 8) & 0xFF);
HardSPI_Transfer(Address & 0xFF);
while (Count--)
{
HardSPI_Transfer(*DataArray++);
}
HardSPI_W_SS(1);
W25Q64_HardWaitBusy();
}
// 硬件SPI扇区擦除
void W25Q64_HardSectorErase(uint32_t Address)
{
W25Q64_HardWriteEnable();
W25Q64_HardWaitBusy();
HardSPI_W_SS(0);
HardSPI_Transfer(W25Q64_CMD_SECTOR_ERASE_4KB);
HardSPI_Transfer((Address >> 16) & 0xFF);
HardSPI_Transfer((Address >> 8) & 0xFF);
HardSPI_Transfer(Address & 0xFF);
HardSPI_W_SS(1);
W25Q64_HardWaitBusy();
}
// 硬件SPI读取数据
void W25Q64_HardReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{
W25Q64_HardWaitBusy();
HardSPI_W_SS(0);
HardSPI_Transfer(W25Q64_CMD_READ_DATA);
HardSPI_Transfer((Address >> 16) & 0xFF);
HardSPI_Transfer((Address >> 8) & 0xFF);
HardSPI_Transfer(Address & 0xFF);
while (Count--)
{
*DataArray++ = HardSPI_Transfer(0xFF);
}
HardSPI_W_SS(1);
}
// 硬件SPI读取JEDEC ID
uint32_t W25Q64_HardReadJEDECID(void)
{
uint32_t JEDECID = 0;
HardSPI_W_SS(0);
HardSPI_Transfer(W25Q64_CMD_JEDEC_ID);
JEDECID |= (uint32_t)HardSPI_Transfer(0xFF) << 16;
JEDECID |= (uint32_t)HardSPI_Transfer(0xFF) << 8;
JEDECID |= HardSPI_Transfer(0xFF);
HardSPI_W_SS(1);
return JEDECID;
}- h文件W25Q64指令声明
// W25Q64指令定义
#define W25Q64_CMD_WRITE_ENABLE 0x06
#define W25Q64_CMD_WRITE_DISABLE 0x04
#define W25Q64_CMD_READ_STATUS_REG1 0x05
#define W25Q64_CMD_READ_STATUS_REG2 0x35
#define W25Q64_CMD_WRITE_STATUS_REG 0x01
#define W25Q64_CMD_PAGE_PROGRAM 0x02
#define W25Q64_CMD_QUAD_PAGE_PROGRAM 0x32
#define W25Q64_CMD_BLOCK_ERASE_64KB 0xD8
#define W25Q64_CMD_BLOCK_ERASE_32KB 0x52
#define W25Q64_CMD_SECTOR_ERASE_4KB 0x20
#define W25Q64_CMD_CHIP_ERASE 0xC7
#define W25Q64_CMD_ERASE_SUSPEND 0x75
#define W25Q64_CMD_ERASE_RESUME 0x7A
#define W25Q64_CMD_POWER_DOWN 0xB9
#define W25Q64_CMD_HIGH_PERFORMANCE_MODE 0xA3
#define W25Q64_CMD_CONTINUOUS_READ_MODE_RESET 0xFF
#define W25Q64_CMD_RELEASE_POWER_DOWN 0xAB
#define W25Q64_CMD_DEVICE_ID 0xAB
#define W25Q64_CMD_MANUFACTURER_DEVICE_ID 0x90
#define W25Q64_CMD_READ_UNIQUE_ID 0x4B
#define W25Q64_CMD_JEDEC_ID 0x9F
#define W25Q64_CMD_READ_DATA 0x03
#define W25Q64_CMD_FAST_READ 0x0B
#define W25Q64_CMD_FAST_READ_DUAL_OUTPUT 0x3B
#define W25Q64_CMD_FAST_READ_QUAD_OUTPUT 0x6B
#define W25Q64_CMD_WORD_READ 0xE8
#define W25Q64_CMD_DUAL_IO_READ 0xBB
#define W25Q64_CMD_QUAD_IO_READ 0xEB