基本信息

  • W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器
  • 常用于数据存储、字库存储、固件程序存储等场景
  • 存储介质:Nor Flash(闪存)
  • 时钟频率:80MHz / 160MHz (Dual SPI) / 320MHz (Quad SPI)

存储容量(24位地址)

型号容量(bit)容量(Byte)
W25Q404Mbit512KByte
W25Q808Mbit1MByte
W25Q1616Mbit2MByte
W25Q3232Mbit4MByte
W25Q6464Mbit8MByte
W25Q128128Mbit16MByte
W25Q256256Mbit32MByte

W21Q64使用步骤

软件SPI操作步骤

步骤操作函数调用参数说明
1初始化软件SPISoftSPI_Init()无参数
2初始化W25Q64W25Q64_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 IDW25Q64_ReadJEDECID()无参数,返回32位JEDEC ID

硬件SPI操作步骤

步骤操作函数调用参数说明
1初始化硬件SPIHardSPI_Init()无参数
2初始化W25Q64W25Q64_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 IDW25Q64_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);
}

配置代码

c
// 写使能
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指令声明

c
// 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