stm32 read and write w25qxx

1. Introduction to w25qxx.

Second, stm32CubeIDE configuration.

Three, the code

1,w25qxx.c



#include "W25Qxx.h"



 /**********************************************************************************
  * 函数功能: 模块初始化
  */
uint8_t BSP_W25Qx_Init(void)
{
    BSP_W25Qx_Reset();
    return BSP_W25Qx_GetStatus();
}

void    BSP_W25Qx_Reset(void)
{
    uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};

    W25Qx_Enable();
    /* Send the reset command */
    HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);
    W25Qx_Disable();

}

 /**********************************************************************************
  * 函数功能: 获取设备状态
  */
uint8_t BSP_W25Qx_GetStatus(void)
{
    uint8_t cmd[] = {READ_STATUS_REG1_CMD};
    uint8_t status;

    W25Qx_Enable();
    /* Send the read status command */
    HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
    /* Reception of the data */
    HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);
    W25Qx_Disable();

    /* Check the value of the register */
  if((status & W25QxxFV_FSR_BUSY) != 0)
  {
    return W25Qx_BUSY;
  }
    else
    {
        return W25Qx_OK;
    }
}

 /**********************************************************************************
  * 函数功能: 写使能
  */
uint8_t BSP_W25Qx_WriteEnable(void)
{
    uint8_t cmd[] = {WRITE_ENABLE_CMD};
    uint32_t tickstart = HAL_GetTick();

    /*Select the FLASH: Chip Select low */
    W25Qx_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Qx_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
        {
                return W25Qx_TIMEOUT;
        }
    }

    return W25Qx_OK;
}

 /**********************************************************************************
  * 函数功能: 获取设备ID
  */
void BSP_W25Qx_Read_ID(uint8_t *ID)
{
    uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};

    W25Qx_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
    /* Reception of the data */
    HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);
    W25Qx_Disable();

}



 /**********************************************************************************
  * 函数功能: 读数据
  * 输入参数: 缓存数组指针、读地址、字节数
  */
uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
    uint8_t cmd[4];

    /* Configure the command */
    cmd[0] = READ_CMD;
    cmd[1] = (uint8_t)(ReadAddr >> 16);
    cmd[2] = (uint8_t)(ReadAddr >> 8);
    cmd[3] = (uint8_t)(ReadAddr);

    W25Qx_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
    /* Reception of the data */
    if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)
  {
    return W25Qx_ERROR;
  }
    W25Qx_Disable();
    return W25Qx_OK;
}

 /**********************************************************************************
  * 函数功能: 写数据
  * 输入参数: 缓存数组指针、写地址、字节数
  */
uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
{
    uint8_t cmd[4];
    uint32_t end_addr, current_size, current_addr;
    uint32_t tickstart = HAL_GetTick();

    /* Calculation of the size between the write address and the end of the page */
  current_addr = 0;

  while (current_addr <= WriteAddr)
  {
    current_addr += W25QxxFV_PAGE_SIZE;
  }
  current_size = current_addr - WriteAddr;

  /* Check if the size of the data is less than the remaining place in the page */
  if (current_size > Size)
  {
    current_size = Size;
  }

  /* Initialize the adress variables */
  current_addr = WriteAddr;
  end_addr = WriteAddr + Size;

  /* Perform the write page by page */
  do
  {
        /* Configure the command */
        cmd[0] = PAGE_PROG_CMD;
        cmd[1] = (uint8_t)(current_addr >> 16);
        cmd[2] = (uint8_t)(current_addr >> 8);
        cmd[3] = (uint8_t)(current_addr);

        /* Enable write operations */
        BSP_W25Qx_WriteEnable();

        W25Qx_Enable();
    /* Send the command */
    if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    {
      return W25Qx_ERROR;
    }

    /* Transmission of the data */
    if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
    {
      return W25Qx_ERROR;
    }
            W25Qx_Disable();
        /* Wait the end of Flash writing */
        while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
        {
            /* Check for the Timeout */
            if((HAL_GetTick() - tickstart) > W25Qx_TIMEOUT_VALUE)
            {
                return W25Qx_TIMEOUT;
            }
        }

    /* Update the address and size variables for next page programming */
    current_addr += current_size;
    pData += current_size;
    current_size = ((current_addr + W25QxxFV_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25QxxFV_PAGE_SIZE;
  } while (current_addr < end_addr);


    return W25Qx_OK;
}

 /**********************************************************************************
  * 函数功能: 扇区擦除
  * 输入参数: 地址
  */
uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)
{
    uint8_t cmd[4];
    uint32_t tickstart = HAL_GetTick();
    cmd[0] = SECTOR_ERASE_CMD;
    cmd[1] = (uint8_t)(Address >> 16);
    cmd[2] = (uint8_t)(Address >> 8);
    cmd[3] = (uint8_t)(Address);

    /* Enable write operations */
    BSP_W25Qx_WriteEnable();

    /*Select the FLASH: Chip Select low */
    W25Qx_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Qx_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Qx_GetStatus() == W25Qx_BUSY);
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25QxxFV_SECTOR_ERASE_MAX_TIME)
        {
                return W25Qx_TIMEOUT;
        }
    }
    return W25Qx_OK;
}

 /**********************************************************************************
  * 函数功能: 芯片擦除
  */
uint8_t BSP_W25Qx_Erase_Chip(void)
{
    uint8_t cmd[4];
    uint32_t tickstart = HAL_GetTick();
    cmd[0] = CHIP_ERASE_CMD;

    /* Enable write operations */
    BSP_W25Qx_WriteEnable();

    /*Select the FLASH: Chip Select low */
    W25Qx_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Qx_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Qx_GetStatus() != W25Qx_BUSY);
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25QxxFV_BULK_ERASE_MAX_TIME)
        {
                return W25Qx_TIMEOUT;
        }
    }
    return W25Qx_OK;
}

/*************************************************/


/*************************************************/

2,w25qxx.h

/*
 * w25qxx.h
 *
 *  Created on: Nov 26, 2022
 *      Author: admin
 */

#ifndef INC_W25QXX_H_
#define INC_W25QXX_H_



#endif /* INC_W25QXX_H_ */


#ifndef __W25Qxx_H
#define __W25Qxx_H

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi.h"
//W25Q128
#define W25QxxFV_FLASH_SIZE                  0x1000000 /* 128 MBits => 16MBytes */
#define W25QxxFV_SECTOR_SIZE                 0x10000   /* 256 sectors of 64KBytes */
#define W25QxxFV_SUBSECTOR_SIZE              0x1000    /* 4096 subsectors of 4kBytes */
#define W25QxxFV_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */
//zyd
//#define W25QxxFV_FLASH_SIZE                  0x800000 /* 64 MBits => 8MBytes */
//#define W25QxxFV_SECTOR_SIZE                 65536   /* 256 sectors of 64KBytes */
//#define W25QxxFV_SUBSECTOR_SIZE              4096    /* 4096 subsectors of 4kBytes */
//#define W25QxxFV_PAGE_SIZE                   256     /* 65536 pages of 256 bytes */

#define W25QxxFV_DUMMY_CYCLES_READ           4
#define W25QxxFV_DUMMY_CYCLES_READ_QUAD      10

#define W25QxxFV_BULK_ERASE_MAX_TIME         250000
#define W25QxxFV_SECTOR_ERASE_MAX_TIME       3000
#define W25QxxFV_SUBSECTOR_ERASE_MAX_TIME    800
#define W25Qx_TIMEOUT_VALUE                   1000

/* Reset Operations */
#define RESET_ENABLE_CMD                     0x66
#define RESET_MEMORY_CMD                     0x99

#define ENTER_QPI_MODE_CMD                   0x38
#define EXIT_QPI_MODE_CMD                    0xFF

/* Identification Operations */
#define READ_ID_CMD                          0x90
#define DUAL_READ_ID_CMD                     0x92
#define QUAD_READ_ID_CMD                     0x94
#define READ_JEDEC_ID_CMD                    0x9F

/* Read Operations */
#define READ_CMD                             0x03
#define FAST_READ_CMD                        0x0B
#define DUAL_OUT_FAST_READ_CMD               0x3B
#define DUAL_INOUT_FAST_READ_CMD             0xBB
#define QUAD_OUT_FAST_READ_CMD               0x6B
#define QUAD_INOUT_FAST_READ_CMD             0xEB

/* Write Operations */
#define WRITE_ENABLE_CMD                     0x06
#define WRITE_DISABLE_CMD                    0x04

/* Register Operations */
#define READ_STATUS_REG1_CMD                  0x05
#define READ_STATUS_REG2_CMD                  0x35
#define READ_STATUS_REG3_CMD                  0x15

#define WRITE_STATUS_REG1_CMD                 0x01
#define WRITE_STATUS_REG2_CMD                 0x31
#define WRITE_STATUS_REG3_CMD                 0x11


/* Program Operations */
#define PAGE_PROG_CMD                        0x02
#define QUAD_INPUT_PAGE_PROG_CMD             0x32


/* Erase Operations */
#define SECTOR_ERASE_CMD                     0x20
#define CHIP_ERASE_CMD                       0xC7

#define PROG_ERASE_RESUME_CMD                0x7A
#define PROG_ERASE_SUSPEND_CMD               0x75


/* Flag Status Register */
#define W25QxxFV_FSR_BUSY                    ((uint8_t)0x01)    /*!< busy */
#define W25QxxFV_FSR_WREN                    ((uint8_t)0x02)    /*!< write enable */
#define W25QxxFV_FSR_QE                      ((uint8_t)0x02)    /*!< quad enable */


#define W25Qx_Enable()             HAL_GPIO_WritePin(W25_CS_GPIO_Port, W25_CS_Pin, GPIO_PIN_RESET)
#define W25Qx_Disable()         HAL_GPIO_WritePin(W25_CS_GPIO_Port, W25_CS_Pin, GPIO_PIN_SET)

#define W25Qx_OK            ((uint8_t)0x00)
#define W25Qx_ERROR         ((uint8_t)0x01)
#define W25Qx_BUSY          ((uint8_t)0x02)
#define W25Qx_TIMEOUT        ((uint8_t)0x03)

uint8_t BSP_W25Qx_Init(void);
void    BSP_W25Qx_Reset(void);
uint8_t BSP_W25Qx_GetStatus(void);
uint8_t BSP_W25Qx_WriteEnable(void);
void BSP_W25Qx_Read_ID(uint8_t *ID);
uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
uint8_t BSP_W25Qx_Erase_Block(uint32_t Address);
uint8_t BSP_W25Qx_Erase_Chip(void);



#endif





3, test

BSP_W25Qx_Read_ID(ID);

 BSP_W25Qx_Write(wr_buf,0,10);
 delay_ms(100);
BSP_W25Qx_Read(rd_buf,0, 10);
 delay_ms(100);
 for(i=0;i<10;i++)
 {
      printf("\r\n rd_buf = %d ",rd_buf[i]);
 }

Four, summary.

8MB=128 blocks (64KB) 1 block=16 sectors (4KB) 1 sector=16 pages (256B)

1 page (page) = 256B

1 sector (sector) = 16 pages (256B) = 16*256 = 4096B = 4KB

1 block ((block) = 16 sectors = 16*4096B = 65536B = 64KB

w25q64 size 64Mbit is 8MByte

As long as the driver is configured with SPI, after configuration, there is generally no problem with reading and writing.

Guess you like

Origin blog.csdn.net/m0_38012497/article/details/128871137