STM32CbueMX之W25Q256

W25Q128和W25Q256指令通用,只是一个是24bit地址另一个是32bit地址。

驱动应该通用(没测试过)。不行就去除BSP_W25Q256_Enter4ByteAddressMode()函数,然后删除read wirte函数的A31-A24位。

STM32CbueMX之W25Q256_第1张图片

/********************************Copyright (c)**********************************\
**
**                   (c) Copyright 2019, Main, China, Sudaroot.
**                           All Rights Reserved
**
**                           By(Sudaroot personally owned)
**                           https://me.csdn.net/sudaroot/
**
**----------------------------------文件信息------------------------------------
** 文件名称: w25q256.c
** 创建人员: Sudaroot
** 创建日期: 2019-07-22
** 文档描述: 
**
**----------------------------------版本信息------------------------------------
** 版本代号: V0.1
** 版本说明: 初始版本
**
**------------------------------------------------------------------------------
\********************************End of Head************************************/

#include "w25q256.h"
extern SPI_HandleTypeDef hspi5;


/**
  * @brief  Initializes the W25Q256FV interface.
  * @retval None
  */
uint8_t BSP_W25Q256_Init(void)
{
    /* Reset W25Q256xx */
    uint8_t res = 0;
    res = BSP_W25Q256_Reset();
    if(res != W25Q256_OK) return res;
    
    res = BSP_W25Q256_Enter4ByteAddressMode();
    return res;
}

/**
  * @brief  This function reset the W25Q256.
  * @retval None
  */
uint8_t BSP_W25Q256_Reset(void)
{
    uint32_t tickstart = HAL_GetTick();
    uint8_t cmd[2] = {RESET_ENABLE_CMD, RESET_MEMORY_CMD};
        
    W25Q256_Enable();
    /* Send the reset command */
    HAL_SPI_Transmit(&hspi5, cmd, 2, W25Q256_TIMEOUT_VALUE);
    W25Q256_Disable();
    
        /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256_TIMEOUT_VALUE)
        {
            return W25Q256_TIMEOUT;
        }
    }

    return W25Q256_OK;

}

/**
  * @brief  Reads current status of the W25Q256FV.
  * @retval W25Q256FV memory status
  */
uint8_t BSP_W25Q256_GetStatus(void)
{
    uint8_t cmd[] = {READ_STATUS_REG1_CMD};
    uint8_t status;

    W25Q256_Enable();
    /* Send the read status command */
    HAL_SPI_Transmit(&hspi5, cmd, 1, W25Q256_TIMEOUT_VALUE);
    /* Reception of the data */
    HAL_SPI_Receive(&hspi5, &status, 1, W25Q256_TIMEOUT_VALUE);
    W25Q256_Disable();

    /* Check the value of the register */
    if((status & W25Q256FV_FSR_BUSY) != 0)
    {
        return W25Q256_BUSY;
    }
    else
    {
        return W25Q256_OK;
    }
}


/**
  * @brief  This function send a Enter 4-Byte Address Mode (B7h)
  * @retval None
  */
uint8_t BSP_W25Q256_Enter4ByteAddressMode(void)
{
    uint8_t cmd[] = {ENTER_4BYTE_ADDRESS_MODE};
    uint32_t tickstart = HAL_GetTick();

    /*Select the FLASH: Chip Select low */
    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 1, W25Q256_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Q256_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256_TIMEOUT_VALUE)
        {
            return W25Q256_TIMEOUT;
        }
    }

    return W25Q256_OK;
}



/**
  * @brief  This function send a Exit 4-Byte Address Mode (E9h)
  * @retval None
  */
uint8_t BSP_W25Q256_Exit4ByteAddressMode(void)
{
    uint8_t cmd[] = {EXIT_4BYTE_ADDRESS_MODE};
    uint32_t tickstart = HAL_GetTick();

    /*Select the FLASH: Chip Select low */
    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 1, W25Q256_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Q256_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256_TIMEOUT_VALUE)
        {
            return W25Q256_TIMEOUT;
        }
    }

    return W25Q256_OK;
}





/**
  * @brief  This function send a Write Enable and wait it is effective.
  * @retval None
  */
uint8_t BSP_W25Q256_WriteEnable(void)
{
    uint8_t cmd[] = {WRITE_ENABLE_CMD};
    uint32_t tickstart = HAL_GetTick();

    /*Select the FLASH: Chip Select low */
    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 1, W25Q256_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Q256_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256_TIMEOUT_VALUE)
        {
            return W25Q256_TIMEOUT;
        }
    }

    return W25Q256_OK;
}

/**
  * @brief  Read Manufacture/Device ID.
	* @param  return value address
  * @retval None
  */
void BSP_W25Q256_Read_ID(uint8_t *ID)
{
    uint8_t cmd[4] = {READ_ID_CMD, 0x00, 0x00, 0x00};

    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 4, W25Q256_TIMEOUT_VALUE);
    /* Reception of the data */
    HAL_SPI_Receive(&hspi5, ID, 2, W25Q256_TIMEOUT_VALUE);
    W25Q256_Disable();

}

/**
  * @brief  Reads an amount of data from the QSPI memory.
  * @param  pData: Pointer to data to be read
  * @param  ReadAddr: Read start address
  * @param  Size: Size of data to read
  * @retval QSPI memory status
  */
uint8_t BSP_W25Q256_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
    uint8_t cmd[5];
    
    /* Check parameter */
    if(ReadAddr >= W25Q256FV_FLASH_SIZE || (ReadAddr + Size) >= W25Q256FV_FLASH_SIZE)
        return W25Q256_ERROR;
    
    /* Configure the command */
    cmd[0] = READ_CMD;
    cmd[1] = (uint8_t)(ReadAddr >> 24);   
    cmd[2] = (uint8_t)(ReadAddr >> 16);
    cmd[3] = (uint8_t)(ReadAddr >> 8);
    cmd[4] = (uint8_t)(ReadAddr);

    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 5, W25Q256_TIMEOUT_VALUE);

    /* Reception of the data */
    if (HAL_SPI_Receive(&hspi5, pData, Size, W25Q256_TIMEOUT_VALUE) != HAL_OK)
    {
        return W25Q256_ERROR;
    }

    W25Q256_Disable();
    return W25Q256_OK;
}

/**
  * @brief  Writes an amount of data to the QSPI memory.
  * @param  pData: Pointer to data to be written
  * @param  WriteAddr: Write start address
  * @param  Size: Size of data to write,No more than 256byte.
  * @retval QSPI memory status
  */
uint8_t BSP_W25Q256_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
{
    uint8_t cmd[5];
    uint32_t end_addr, current_size, current_addr;
    uint32_t tickstart = HAL_GetTick();

    /* Check parameter */
    if(WriteAddr >= W25Q256FV_FLASH_SIZE || (WriteAddr + Size) >= W25Q256FV_FLASH_SIZE)
        return W25Q256_ERROR;
    
    /* Calculation of the size between the write address and the end of the page */
    current_addr = 0;

    while (current_addr <= WriteAddr)
    {
        current_addr += W25Q256FV_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 >> 24);
        cmd[2] = (uint8_t)(current_addr >> 16);
        cmd[3] = (uint8_t)(current_addr >> 8);
        cmd[4] = (uint8_t)(current_addr);

        /* Enable write operations */
        BSP_W25Q256_WriteEnable();

        W25Q256_Enable();

        /* Send the command */
        if (HAL_SPI_Transmit(&hspi5, cmd, 5, W25Q256_TIMEOUT_VALUE) != HAL_OK)
        {
            return W25Q256_ERROR;
        }

        /* Transmission of the data */
        if (HAL_SPI_Transmit(&hspi5, pData, current_size, W25Q256_TIMEOUT_VALUE) != HAL_OK)
        {
            return W25Q256_ERROR;
        }

        W25Q256_Disable();

        /* Wait the end of Flash writing */
        while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
        {
            /* Check for the Timeout */
            if((HAL_GetTick() - tickstart) > W25Q256_TIMEOUT_VALUE)
            {
                return W25Q256_TIMEOUT;
            }
        }

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


    return W25Q256_OK;
}






uint8_t BSP_W25Q256_Erase_Sector(uint32_t Address)
{
    uint8_t cmd[5];
    uint32_t tickstart = HAL_GetTick();
    
        /* Check parameter */
    if(Address >= W25Q256FV_FLASH_SIZE)
        return W25Q256_ERROR;
    
    cmd[0] = SECTOR_ERASE_CMD;
    cmd[1] = (uint8_t)(Address >> 24);
    cmd[2] = (uint8_t)(Address >> 16);
    cmd[3] = (uint8_t)(Address >> 8);
    cmd[4] = (uint8_t)(Address);

    /* Enable write operations */
    BSP_W25Q256_WriteEnable();

    /*Select the FLASH: Chip Select low */
    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 5, W25Q256_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Q256_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256FV_SECTOR_ERASE_MAX_TIME)
        {
            return W25Q256_TIMEOUT;
        }
    }
    return W25Q256_OK;
}



/**
  * @brief  Erases the specified block of the QSPI memory.
  * @param  BlockAddress: Block address to erase
  * @retval QSPI memory status
  */
uint8_t BSP_W25Q256_Erase_Block(uint32_t Address)
{
    uint8_t cmd[5];
    uint32_t tickstart = HAL_GetTick();
    
    if(Address >= W25Q256FV_FLASH_SIZE)
        return W25Q256_ERROR;
    
    cmd[0] = BLOCK_ERASE_CMD;
    cmd[1] = (uint8_t)(Address >> 24);
    cmd[2] = (uint8_t)(Address >> 16);
    cmd[3] = (uint8_t)(Address >> 8);
    cmd[4] = (uint8_t)(Address);

    /* Enable write operations */
    BSP_W25Q256_WriteEnable();

    /*Select the FLASH: Chip Select low */
    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 5, W25Q256_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Q256_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() == W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256FV_BLOCK_ERASE_MAX_TIME)
        {
            return W25Q256_TIMEOUT;
        }
    }
    return W25Q256_OK;
}

/**
  * @brief  Erases the entire QSPI memory.This function will take a very long time.
  * @retval QSPI memory status
  */
uint8_t BSP_W25Q256_Erase_Chip(void)
{
    uint8_t cmd[4];
    uint32_t tickstart = HAL_GetTick();
    cmd[0] = CHIP_ERASE_CMD;

    /* Enable write operations */
    BSP_W25Q256_WriteEnable();

    /*Select the FLASH: Chip Select low */
    W25Q256_Enable();
    /* Send the read ID command */
    HAL_SPI_Transmit(&hspi5, cmd, 1, W25Q256_TIMEOUT_VALUE);
    /*Deselect the FLASH: Chip Select high */
    W25Q256_Disable();

    /* Wait the end of Flash writing */
    while(BSP_W25Q256_GetStatus() != W25Q256_BUSY)
    {
        /* Check for the Timeout */
        if((HAL_GetTick() - tickstart) > W25Q256FV_BULK_ERASE_MAX_TIME)
        {
            return W25Q256_TIMEOUT;
        }
    }
    return W25Q256_OK;
}


 
/********************************End of File************************************/
/********************************Copyright (c)**********************************\
**
**                   (c) Copyright 2019, Main, China, Sudaroot.
**                           All Rights Reserved
**
**                           By(Sudaroot personally owned)
**                           https://me.csdn.net/sudaroot/
**
**----------------------------------文件信息------------------------------------
** 文件名称: w25q256.h
** 创建人员: Sudaroot
** 创建日期: 2019-07-22
** 文档描述: 
**
**----------------------------------版本信息------------------------------------
** 版本代号: V0.1
** 版本说明: 初始版本
**
**------------------------------------------------------------------------------
\********************************End of Head************************************/
 
#ifndef __W25Q256_H_
#define __W25Q256_H_

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/** @addtogroup BSP
  * @{
  */

/** @addtogroup Components
  * @{
  */

/** @addtogroup W25Q256FV
  * @{
  */

/** @defgroup W25Q256FV_Exported_Types
  * @{
  */

/**
  * @}
  */

/** @defgroup W25Q256FV_Exported_Constants
  * @{
  */

/**
  * @brief  W25Q256FV Configuration
  */
#define W25Q256FV_FLASH_SIZE                  0x2000000 /* 256 MBits => 32MBytes */
#define W25Q256FV_BLOCK_SIZE                  0x10000   /* 512 sectors of 64KBytes */
#define W25Q256FV_SECTOR_SIZE                 0x1000    /* 4096 subsectors of 4kBytes */
#define W25Q256FV_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */

#define W25Q256FV_DUMMY_CYCLES_READ           4
#define W25Q256FV_DUMMY_CYCLES_READ_QUAD      10

#define W25Q256FV_BULK_ERASE_MAX_TIME         400000
#define W25Q256FV_BLOCK_ERASE_MAX_TIME        5000
#define W25Q256FV_SECTOR_ERASE_MAX_TIME       2000
#define W25Q256_TIMEOUT_VALUE                 1000

/**
  * @brief  W25Q256FV Commands
  */
/* 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 READ_4BTYEADDR_CMD                   0x13
#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 BLOCK_ERASE_CMD                      0xD8
#define CHIP_ERASE_CMD                       0xC7

#define PROG_ERASE_RESUME_CMD                0x7A
#define PROG_ERASE_SUSPEND_CMD               0x75

/* Address Mode */
#define ENTER_4BYTE_ADDRESS_MODE             0xB7
#define EXIT_4BYTE_ADDRESS_MODE              0xE9

/* Flag Status Register */
#define W25Q256FV_FSR_BUSY                    ((uint8_t)0x01)    /*!< busy */
#define W25Q256FV_FSR_WREN                    ((uint8_t)0x02)    /*!< write enable */
#define W25Q256FV_FSR_QE                      ((uint8_t)0x02)    /*!< quad enable */


#define W25Q256_Enable() 			        HAL_GPIO_WritePin(W25Q256_CS_GPIO_Port, W25Q256_CS_Pin, GPIO_PIN_RESET)
#define W25Q256_Disable() 		            HAL_GPIO_WritePin(W25Q256_CS_GPIO_Port, W25Q256_CS_Pin, GPIO_PIN_SET)

#define W25Q256_OK                          ((uint8_t)0x00)
#define W25Q256_ERROR                       ((uint8_t)0x01)
#define W25Q256_BUSY                        ((uint8_t)0x02)
#define W25Q256_TIMEOUT				        ((uint8_t)0x03)


uint8_t BSP_W25Q256_Init(void);
uint8_t	BSP_W25Q256_Reset(void);
uint8_t BSP_W25Q256_GetStatus(void);
uint8_t BSP_W25Q256_WriteEnable(void);
void    BSP_W25Q256_Read_ID(uint8_t *ID);
uint8_t BSP_W25Q256_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
uint8_t BSP_W25Q256_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
uint8_t BSP_W25Q256_Erase_Sector(uint32_t Address);
uint8_t BSP_W25Q256_Erase_Block(uint32_t Address);
uint8_t BSP_W25Q256_Erase_Chip(void);
uint8_t BSP_W25Q256_Enter4ByteAddressMode(void);
uint8_t BSP_W25Q256_Exit4ByteAddressMode(void);


/**
  * @}
  */

/** @defgroup W25Q256FV_Exported_Functions
  * @{
  */
/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

#ifdef __cplusplus
}
#endif


#endif /* __W25Q256_H */

 
/********************************End of File************************************/

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
    /* USER CODE BEGIN 1 */
    unsigned int i;
    /* USER CODE END 1 */


    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_SPI5_Init();
    MX_USART1_UART_Init();
    /* USER CODE BEGIN 2 */
    HAL_Delay(1000);

    printf("sudaroot\r\n");
    BSP_W25Q256_Init();
    BSP_W25Q256_Read_ID(id);
    printf("ID = 0x%02X%02X\r\n", id[0], id[1]);

    printf("1.BSP_W25Q256_Erase_Block = %d\r\n", BSP_W25Q256_Erase_Block(0));
    memset(temp, 0xAB, 10);
    printf("2.BSP_W25Q256_Write = %d\r\n", BSP_W25Q256_Write(temp, 0, 10));

    printf("3.BSP_W25Q256_Read = %d\r\n", BSP_W25Q256_Read(temp, 0, 10));
    for(i = 0; i < 10; i++)
        printf("temp[%d] = 0x%02X\r\n", i, temp[i]);

    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */

        /* USER CODE BEGIN 3 */
    }

    /* USER CODE END 3 */
}

  全篇完。

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!

 STM32CbueMX之W25Q256_第2张图片

 

你可能感兴趣的:(STM32,stm32,arm,嵌入式硬件)