GD32读写FlashGDw25Q64
1.原理图
2.介绍
-
本实验由国产的单片机GD32F4VKT6配合国产的Flash来完成
-
SPI0连接到Flash接口。
2.1Flash介绍
-
GDW25Q64,是一种高性能的串行SPI FLASH存储器,由华邦公司生产。它具有64兆位(8兆字节)的存储容量,并广泛应用于数据存储、字库存储、固件程序存储等场景。W25Q64的存储结构由块(Block)、扇区(Sector)和页(Page)组成,共有128个块,每个块包含16个扇区,每个扇区包含16个页,每页最多可存储256字节的数据。
技术规格:
存储容量:8Mb
存储单元:128块,每块16扇区,每扇区16页,每页256字节
工作电压:2.7V至3.6V
电流消耗:活跃状态下<5mA,掉电模式下<1uA
SPI模式:支持标准、双倍和四倍SPI
性能:擦写周期多达10万次,数据保存可达20年
安全性:提供软件和硬件写保护、扇区和块保护等功能
标准SPI:该GD25064E具有4个信号总线串行外设接口:串行时钟(SCLK),芯片选择(CS#),串行数据输入(SL)和串行数据输出(SO)。同时支持SPI总线模式0和3。输入数据在SCLK的上升沿锁存,数据在SCLK的下降沿移出。
双SPI:该GD25064E支持双SPI操作时,使用“双输出快速读取”和“双升/0快速读取”(3BH和BBH)命令。
-
这些命令允许以两倍于标准SPI的速率向设备传输数据或从设备传输数据。
-
当使用双SPI命令时Sl和SO引脚变成双向L/0引脚:100和I01。
四SPI:该GD25064E支持四SPI操作时,使用“四输出快速读取”“四通道快速读取”(6BH,EBH)命令的。
-
这些命令允许以标准SPI的四倍速率向设备传输数据或从设备传输数据。
-
使用QuadSPI命令时SI和S0引脚变为双向L/0引脚:10和I01,WP#和HOLD#引脚变为双向L/0引脚:102和I03。
-
0uad SPl命令要求状态寄存器中的非易失性Quad使能位(OE)设置为1。
保持功能:当QE=0时,HOLD函数可用。如果QE=1,则HOLD功能被禁用,HOLD#引脚作为专用数据L/0引脚。
-
HOLD#信号变低以停止与设备的任何串行通信,除了写状态寄存器、编程或正在进行的擦除操作。
-
HOLD的操作需要CS#保持低电平,并从HOLD#信号的下降沿开始,SCLK信号为低电平。
-
如果SCLK不低,HOLD操作将不会启动,直到SCLK低。HOLD条件结束于HOLD#信号的上升沿,SCLK为低。如果SCLK不低,HOLD操作将不会结束,直到SCLK低。SO是高阻抗的,SI和SCLK都不关心在HOLD操作。
-
如果CS#在HOLD操作期间被驱动为高电平,它将重置设备的内部逻辑。要重新启动与芯片的通信,HOLD#必须在高,然后CS#必须在低。
引脚说明:
-
/CS:片选输入
-
DO(IO1):数据输出(数据输入输出1)
-
/WP(IO2):写保护输入(数据输入输出2)
-
GND:地信号
-
DI(IO0):数据输入(数据输入输出0)
-
CLK:串行时钟输入
-
/HOLD(IO3):保持输入(数据输入输出3)
-
VCC:电源
应用场景:
W25Q64适用于存储图片数据、字库数据、音频数据、保存设备运行日志文件等。其高效的连续读取模式和低功耗特性使其在各种嵌入式系统中得到广泛应用。
综上所述,W25Q64是一款性能优异、安全性高、功耗低的SPI FLASH存储器,适用于多种数据存储需求,特别是在资源受限的嵌入式系统中 1 4 。
2.2MCU介绍
-
采用国产的ARM架构的GD32F427VKT6
-
GD32F4产品系列紧贴市场高端需求,以高性能、强实时、大容量特性,强化更为广泛的市场领先优势。 GD32F4系列MCU采用Arm® Cortex®-M4内核,处理器主频高达240MHz,可支持算法复杂度更高的嵌入式应用,具备更快速的实时处理能力,并拥有业界领先的大容量存储优势。 GD32F4系列具有丰富的外设资源特性,可提供多达4个USART和4个UART,3个I2C,6个SPI,2个I2S,2个CAN2.0B、1个SDIO接口、1个10/100M以太网控制器,并支持USB2.0 FS和HS通信。还配备了3个采样率高达2.6M SPS的12位高速ADC和2个12位DAC。 此外GD32F4产品系列集成了TFT LCD控制器和硬件图形加速器IPA, 以实现液晶驱动并显著提升显示图像显示画质。还支持8位至14位的Camera视频接口,便于连接数字摄像头并实现图像采集与传输。 GD32F470/F427/F425系列产品与GD32F450/F407/F405系列产品完全兼容,广泛应用于高级计算,云服务器,人工智能、工业控制、电机变频、图形显示、安防监控、传感器网络、无人机、机器人、物联网等创新领域。
3.代码介绍
3.1 main函数
本实验就是往Flash 0地址写入数据。
int main(void)
{
/* 初始化滴答定时器 */
systick_config();
/* 串口初始化 */
AllUsartInit();
/* 初始化led */
ledInit();
/* 初始化SPI */
SPI0_Init();
BSP_W25Qx_Init();//flash初始化
BSP_W25Qx_Read_ID(ID);//读取ID
printf("ID[0]=%d\n",ID[0]);
printf("ID[1]=%d\n",ID[1]);
if (BSP_W25Qx_64k_Block(0) == W25Qx_OK)//擦除一个块
{
printf(" Sector Erase ok\r\n");
}
else
{
printf("error");
}
while (1)
{
memset(wData1, 0, sizeof(wData1));
memset(rData1,0,sizeof(rData1));
//往Flash写入数据,我这儿是将数组中的100个数据写入Flash.
参数介绍:
1.wData2:要写入的数据地址
2.0:Flash存储位置的地址
3.100:存储位置的大小,
if (BSP_W25Qx_Write(wData2, 0, 100) == W25Qx_OK)
{
printf("Write0 sucess ok\n");
}
else
{
printf("Write0 error\n");
}
// 读取数据从flash的零地址开始,一直读100个数据
if (BSP_W25Qx_Read(rData2, 0, 100) == W25Qx_OK) {
for (i = 0; i < 100; i++) {
printf("rData2[%d] = %d ", i, rData2[i]);
}
}
else
{
printf("Read error\n");
}
delay_1ms(2000);
}
}
3.2 SPI初始化
/*********************************************************************************************************
** Function name: SPI0_Init
** Descriptions: SPI0初始化(SPI0与W25Q64 Flash连接)
** input parameters: 无
** output parameters: 无
** Returned value: 无
*********************************************************************************************************/
void SPI0_Init(void)
{
spi_parameter_struct spi_init_struct;
spi_i2s_deinit(SPI0);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_SPI0);
/* configure SPI0 GPIO */
gpio_af_set(GPIOA, GPIO_AF_5, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
/* set SPI0_NSS as GPIO*/
gpio_af_set(GPIOA, GPIO_AF_5, GPIO_PIN_4);
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
gpio_bit_set(GPIOA, GPIO_PIN_4);
/* SPI0 parameter config */
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;//双工模式
spi_init_struct.device_mode = SPI_MASTER;//作为master,提供SCLK
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;//8bit模式
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;//mode0
spi_init_struct.nss = SPI_NSS_SOFT;
spi_init_struct.prescale = SPI_PSC_64;// 分频比
spi_init_struct.endian = SPI_ENDIAN_MSB;//高位在前
spi_init(SPI0, &spi_init_struct);
/* SPI enable */
spi_enable(SPI0);
}
3.3 驱动介绍
#include "w25qxx_spi.h"
#include "systick.h"
/*Flash介绍
*8M=128块
*1块=16扇区
*1扇区=16页区
*1页区=256字节。
*/
/**
* @brief spi数据传输函数
* @param spi_per spi外设
* @param byte 发送字节
* @return 接收字节
*/
uint8_t spi_SendRcvByte(uint32_t spi_per, uint8_t byte)
{
uint8_t data;
// 等待发送缓冲区为空
while (RESET == spi_i2s_flag_get(spi_per, SPI_FLAG_TBE))
;
// 发送数据
spi_i2s_data_transmit(spi_per, byte);
// 等待发送完成
while (SET == spi_i2s_flag_get(spi_per, SPI_FLAG_TRANS))
;
// 等待接收缓冲区非空
while (RESET == spi_i2s_flag_get(spi_per, SPI_FLAG_RBNE))
;
// 接收数据
data = spi_i2s_data_receive(spi_per);
// 等待发送完成
while (SET == spi_i2s_flag_get(spi_per, SPI_FLAG_TRANS))
;
return data;
}
/**
* @brief 初始化Flash芯片
* @retval None
*/
uint8_t BSP_W25Qx_Init(void)
{
/* Reset W25Qxxx */
BSP_W25Qx_Reset();
return BSP_W25Qx_GetStatus();
}
/**
* @brief This function reset the W25Qx.
* @retval None
*/
static void BSP_W25Qx_Reset(void)
{
uint8_t cmd[2] = {RESET_ENABLE_CMD, RESET_MEMORY_CMD};
uint32_t i;
W25Qx_Enable();
/* Send the reset command */
for (i = 0; i < 2; i++)
{
spi_SendRcvByte(SPI0, cmd[i]);
}
// HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);
W25Qx_Disable();
}
/**
* @brief Reads current status of the W25Q64.
* @retval W25Q128FV memory status
*/
static uint8_t BSP_W25Qx_GetStatus(void)
{
uint8_t cmd[] = {READ_STATUS_REG1_CMD};
uint8_t status;
W25Qx_Enable();
/* Send the read status command */
// spi_write_byte(SPI0, cmd[0]);
// HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
/* Reception of the data */
// status=spi_read_byte(SPI0);
// HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);
spi_SendRcvByte(SPI0, cmd[0]);
status = spi_SendRcvByte(SPI0, 0x00);
W25Qx_Disable();
/* Check the value of the register */
if ((status & W25Q128FV_FSR_BUSY) != 0)
{
return W25Qx_BUSY;
}
else
{
return W25Qx_OK;
}
}
/**
* @brief This function send a Write Enable and wait it is effective.
* @retval None
*/
uint8_t BSP_W25Qx_WriteEnable(void)
{
uint8_t cmd[] = {WRITE_ENABLE_CMD};
// uint32_t tickstart = HAL_GetTick();
uint32_t tickstart = 0;
/*Select the FLASH: Chip Select low */
W25Qx_Enable();
/* Send the read ID command */
// HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
spi_SendRcvByte(SPI0, cmd[0]);
/*Deselect the FLASH: Chip Select high */
W25Qx_Disable();
/* Wait the end of Flash writing */
while (BSP_W25Qx_GetStatus() == W25Qx_BUSY)
{
tickstart++;
delay_1ms(1);
/* Check for the Timeout */
if (tickstart > W25Qx_TIMEOUT_VALUE)
{
return W25Qx_TIMEOUT;
}
}
return W25Qx_OK;
}
/**
* @brief Read Manufacture/Device ID.
* @param return value address
* @retval None
*/
void BSP_W25Qx_Read_ID(uint8_t *ID)
{
uint8_t cmd[4] = {READ_ID_CMD, 0x00, 0x00, 0x00};
uint32_t i;
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);
for (i = 0; i < 4; i++)
{
spi_SendRcvByte(SPI0, cmd[i]);
}
for (i = 0; i < 2; i++)
{
ID[i] = spi_SendRcvByte(SPI0, 0x00);
}
W25Qx_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_W25Qx_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size)
{
uint8_t cmd[4];
uint8_t status;
uint32_t i;
/* 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);
for (i = 0; i < 4; i++)
spi_SendRcvByte(SPI0, cmd[i]);
/* Reception of the data */
// if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)
// {
// return W25Qx_ERROR;
// }
for (i = 0; i < Size; i++)
pData[i] = spi_SendRcvByte(SPI0, 0x00);
if (status != 0x00)
{
return W25Qx_ERROR;
}
W25Qx_Disable();
return W25Qx_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_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 = 0;
uint32_t i;
/* Calculation of the size between the write address and the end of the page */
current_addr = 0;
while (current_addr <= WriteAddr) // 判断地址属于哪一扇区开始
{
current_addr += W25Q64_PAGE_SIZE; // 0x100-> 256 bytes
}
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;
// }
for (i = 0; i < 4; i++)
spi_SendRcvByte(SPI0, cmd[i]);
/* Transmission of the data */
// if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
// {
// return W25Qx_ERROR;
// }
for (i = 0; i < current_size; i++)
spi_SendRcvByte(SPI0, pData[i]);
W25Qx_Disable();
/* Wait the end of Flash writing */
while (BSP_W25Qx_GetStatus() == W25Qx_BUSY)
{
tickstart++;
delay_1ms(1);
/* Check for the Timeout */
if (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 + W25Q64_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q64_PAGE_SIZE;
} while (current_addr < end_addr);
return W25Qx_OK;
}
/*
函数:读第几页数据,总页数:256*128=32768个页
pData:保存页的数据
PageNum:将数据读第几页
Size:读的数据(设计1页之内)
*/
uint8_t BSP_W25Qx_ReadPage(uint8_t *pData, uint32_t PageNum, uint32_t PageSize)
{
return BSP_W25Qx_Read(pData,PageNum*W25Q64_PAGE_SIZE,PageSize);
}
/*
函数:写第几页数据,总页数:256*128=32768个页
pData:写入页的数据
PageNum:将数据写入第几页
Size:写入的数据(超过一页的大小,数据会丢弃,默认最大写一页)
*/
uint8_t BSP_W25Qx_WriteToPage(uint8_t *pData, uint32_t PageNum, uint32_t Size)
{
return BSP_W25Qx_Write(pData,PageNum*W25Q64_PAGE_SIZE,Size);
}
/**
* @brief 擦除扇区
* @param BlockAddress: Block address to erase
* @retval QSPI memory status
*/
uint8_t BSP_W25Qx_4k_Block(uint32_t Address)
{
uint8_t cmd[4];
uint32_t tickstart = 0;
uint32_t i;
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);
for (i = 0; i < 4; i++)
spi_SendRcvByte(SPI0, cmd[i]);
/*Deselect the FLASH: Chip Select high */
W25Qx_Disable();
delay_1ms(1);
/* Wait the end of Flash writing */
while (BSP_W25Qx_GetStatus() == W25Qx_BUSY)
{
tickstart++;
delay_1ms(1);
/* Check for the Timeout */
if (tickstart > W25Q128FV_SECTOR_ERASE_MAX_TIME)
{
return W25Qx_TIMEOUT;
}
}
return W25Qx_OK;
}
//擦除块
uint8_t BSP_W25Qx_64k_Block(uint32_t Address)
{
uint8_t cmd[4];
uint32_t tickstart = 0;
uint32_t i;
cmd[0] = SECTOR_Block_Erase ;
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);
for (i = 0; i < 4; i++)
spi_SendRcvByte(SPI0, cmd[i]);
/*Deselect the FLASH: Chip Select high */
W25Qx_Disable();
delay_1ms(1);
/* Wait the end of Flash writing */
while (BSP_W25Qx_GetStatus() == W25Qx_BUSY)
{
tickstart++;
delay_1ms(1);
/* Check for the Timeout */
if (tickstart > W25Q128FV_SECTOR_ERASE_MAX_TIME)
{
return W25Qx_TIMEOUT;
}
}
return W25Qx_OK;
}
/**
* @brief 用于擦除GDW25Q64 Flash存储器的整个芯片。This function will take a very long time.
* @retval QSPI memory status
*/
uint8_t BSP_W25Qx_Erase_Chip(void)
{
uint8_t cmd[4];
uint32_t tickstart;
cmd[0] = SECTOR_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);
spi_SendRcvByte(SPI0, cmd[0]);
/*Deselect the FLASH: Chip Select high */
W25Qx_Disable();
/* Wait the end of Flash writing */
while (BSP_W25Qx_GetStatus() != W25Qx_BUSY)
{
tickstart++;
delay_1ms(1);
/* Check for the Timeout */
if (tickstart > W25Q128FV_BULK_ERASE_MAX_TIME)
{
return W25Qx_TIMEOUT;
}
}
return W25Qx_OK;
}
#ifndef _W25QXX_SPI_H
#define _W25QXX_SPI_H
/*********************************************************************************************************
*
* File : W25Qx.h
* Hardware Environment:
* Build Environment : RealView MDK-ARM Version: 5.15
* Version : V1.0
* By :
*
* (c) Copyright 2005-2015, WaveShare
* http://www.waveshare.net
* All Rights Reserved
*
*********************************************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __W25Qx_H
#define __W25Qx_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "spi.h"
#include "gd32f4xx.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup Components
* @{
*/
/** @addtogroup W25Q128FV
* @{
*/
/** @defgroup W25Q128FV_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup W25Q128FV_Exported_Constants
* @{
*/
/**
* @brief W25Q128FV Configuration
*/
#define W25Q64_FLASH_SIZE 0x800000 /* 64 MBit => 8 MBytes */
#define W25Q64_SECTOR_SIZE 0x10000 /* 128 sectors of 64KBytes */
#define W25Q64_SUBSECTOR_SIZE 0x1000 /* 1024 subsectors of 4kBytes */
#define W25Q64_PAGE_SIZE 0x100 /* 16384 pages of 256 bytes */
#define W25Q64_DUMMY_CYCLES_READ 4
#define W25Q64_DUMMY_CYCLES_READ_QUAD 10
//超时时间:当函数读写操作超过一定时间将返回。
#define W25Q128FV_BULK_ERASE_MAX_TIME 250000
#define W25Q128FV_SECTOR_ERASE_MAX_TIME 3000
#define W25Q128FV_SUBSECTOR_ERASE_MAX_TIME 800
#define W25Qx_TIMEOUT_VALUE 1000
/**
* @brief W25Q128FV 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 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 SECTOR_Block_Erase 0xD8 //擦除块指令
#define CHIP_ERASE_CMD 0xC7
#define PROG_ERASE_RESUME_CMD 0x7A
#define PROG_ERASE_SUSPEND_CMD 0x75
/* Flag Status Register */
#define W25Q128FV_FSR_BUSY ((uint8_t)0x01) /*!< busy */
#define W25Q128FV_FSR_WREN ((uint8_t)0x02) /*!< write enable */
#define W25Q128FV_FSR_QE ((uint8_t)0x02) /*!< quad enable */
//spi的NSS使能管脚
#define W25Qx_Enable() gpio_bit_reset(GPIOA,GPIO_PIN_4)
#define W25Qx_Disable() gpio_bit_set(GPIOA,GPIO_PIN_4)
//状态
#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);//初始化
static void BSP_W25Qx_Reset(void);//复位
static uint8_t BSP_W25Qx_GetStatus(void);//状态
uint8_t BSP_W25Qx_WriteEnable(void);//写使能
void BSP_W25Qx_Read_ID(uint8_t *ID);//读设备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_4k_Block(uint32_t Address);//擦除4K的空间--即擦除扇区
uint8_t BSP_W25Qx_64k_Block(uint32_t Address);//擦除64K的空间--即擦除块
uint8_t BSP_W25Qx_Erase_Chip(void);//擦除整个芯片
uint8_t BSP_W25Qx_WriteToPage(uint8_t *pData, uint32_t PageNum, uint32_t Size);//写入页
uint8_t BSP_W25Qx_ReadPage(uint8_t *pData, uint32_t PageNum, uint32_t PageSize);/*读一页*/
/**
* @}
*/
/** @defgroup W25Q128FV_Exported_Functions
* @{
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __W25Qx_H */
#endif