基于Stm32硬件SPI控制GD25QFlash

/**
  *********************************************************************************************************
  * @file    hal_spiflash.c
  * @author  Movebroad -- KK
  * @version V1.0
  * @date    2018-07-24
  * @brief   SPI FLASH GD25Q80CSIG Device
  *		   SPI FLASH GD25Q40BSIG Device
  *********************************************************************************************************
  * @attention
  *		   NSS  : PB12
  *		   SCK  : PA5
  *		   MOSI : PA7
  *		   MISO : PA6
  *********************************************************************************************************
  */

#include "hal_spiflash.h"
#include "platform_config.h"
#include "platform_map.h"
#include "delay.h"
#include "usart.h"

SPI_HandleTypeDef GD25Q_SPIFLASH_Handler;
GD25Q_StatusTypeDef GD25QStatus = GD25Q80CSIG_OK;

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_Init(void)
 @Description			GD25Q_SPIFLASH_Init			: GD25Q SPIFLASH 初始化
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_Init(void)
{
	u32 ReadIdentificationID;
	GD25QStatus = GD25Q80CSIG_OK;
	
	GD25Q_SPIFLASH_Handler.Instance				= GD25Q_FLASH_SPIx;						//SPI1
	GD25Q_SPIFLASH_Handler.Init.Mode				= SPI_MODE_MASTER;						//设置SPI工作模式为主模式
	GD25Q_SPIFLASH_Handler.Init.Direction			= SPI_DIRECTION_2LINES;					//设置SPI数据模式为双线模式
	GD25Q_SPIFLASH_Handler.Init.DataSize			= SPI_DATASIZE_8BIT;					//设置SPI数据大小为8位帧结构
	GD25Q_SPIFLASH_Handler.Init.CLKPolarity			= SPI_POLARITY_HIGH;					//串行同步时钟的空闲状态为高电平
	GD25Q_SPIFLASH_Handler.Init.CLKPhase			= SPI_PHASE_2EDGE;						//串行同步时钟的第二个跳变沿数据被采样
	GD25Q_SPIFLASH_Handler.Init.NSS				= SPI_NSS_SOFT;						//NSS信号由软件控制
	
#ifndef SYSTEMCLOCK
	#error No Define SYSTEMCLOCK!
#else
#if (SYSTEMCLOCK == SYSTEMCLOCKMSI)
	GD25Q_SPIFLASH_Handler.Init.BaudRatePrescaler	= SPI_BAUDRATEPRESCALER_2;				//定义波特率与分频值
#elif (SYSTEMCLOCK == SYSTEMCLOCKHSI)
	GD25Q_SPIFLASH_Handler.Init.BaudRatePrescaler	= SPI_BAUDRATEPRESCALER_8;				//定义波特率与分频值
#else
	#error SYSTEMCLOCK Define Error
#endif
#endif
	
	GD25Q_SPIFLASH_Handler.Init.FirstBit			= SPI_FIRSTBIT_MSB;						//数据传输从MSB位开始
	GD25Q_SPIFLASH_Handler.Init.TIMode				= SPI_TIMODE_DISABLE;					//关闭TI模式
	GD25Q_SPIFLASH_Handler.Init.CRCCalculation		= SPI_CRCCALCULATION_DISABLE;				//关闭硬件CRC校验
	GD25Q_SPIFLASH_Handler.Init.CRCPolynomial		= 10;								//CRC值计算多项式
	
	if (HAL_SPI_Init(&GD25Q_SPIFLASH_Handler) != HAL_OK) {
		/* Initialization Error */
		GD25QStatus = GD25Q80CSIG_ERROR;
	}
	
	GD25Q_SPIFLASH_WakeUp();
	ReadIdentificationID = GD25Q_SPIFLASH_ReadIdentificationID();
	if ((ReadIdentificationID != GD25Q80CSIGIdentificationID) && (ReadIdentificationID != GD25Q40BSIGIdentificationID)) {
		GD25QStatus = GD25Q80CSIG_ERROR;
	}
}

/**********************************************************************************************************
 @Function			GD25Q_StatusTypeDef GD25Q_SPIFLASH_Get_Status(void)
 @Description			GD25Q_SPIFLASH_Get_Status	: GD25Q SPIFLASH 状态
 @Input				void
 @Return				GD25Q_StatusTypeDef
**********************************************************************************************************/
GD25Q_StatusTypeDef GD25Q_SPIFLASH_Get_Status(void)
{
#ifdef	GD25Q_80CSIG
	return GD25QStatus;
#else
	return GD25Q80CSIG_ERROR;
#endif
}

/**********************************************************************************************************
 @Function			u8 GD25Q_SPI_FLASH_ReadByte(void)
 @Description			GD25Q_SPI_FLASH_ReadByte		: SPI FLASH 读取一个字节数据
 @Input				void
 @Return				readByte					: 读取到的数据
**********************************************************************************************************/
u8 GD25Q_SPI_FLASH_ReadByte(void)
{
	u8 readByte, sendByte = GD25Q_Dummy_Byte;
	
	if (HAL_SPI_TransmitReceive(&GD25Q_SPIFLASH_Handler, &sendByte, &readByte, 1, 500) != HAL_OK) {
		readByte = GD25Q_Dummy_Byte;
	}
	return readByte;
}

/**********************************************************************************************************
 @Function			u8 GD25Q_SPI_FLASH_SendByte(u8 byte)
 @Description			GD25Q_SPI_FLASH_SendByte		: SPI FLASH 发送一个字节数据
 @Input				byte						: 发送的数据
 @Return				void
**********************************************************************************************************/
u8 GD25Q_SPI_FLASH_SendByte(u8 byte)
{
	u8 readByte = 0x00, sendByte = byte;
	
	if (HAL_SPI_TransmitReceive(&GD25Q_SPIFLASH_Handler, &sendByte, &readByte, 1, 500) != HAL_OK) {
		readByte = GD25Q_Dummy_Byte;
	}
	return readByte;
}

/**********************************************************************************************************
 @Function			u32 GD25Q_SPIFLASH_ReadDeviceID(void)
 @Description			GD25Q_SPIFLASH_ReadDeviceID			: GD25Q SPIFLASH 读取设备ID
 @Input				void
 @Return				设备ID
**********************************************************************************************************/
u32 GD25Q_SPIFLASH_ReadDeviceID(void)
{
	u32 deviceID = 0;
	
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_DeviceID);
	GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	deviceID = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return deviceID;
}

/**********************************************************************************************************
 @Function			u32 GD25Q_SPIFLASH_ReadManufactureID(void)
 @Description			GD25Q_SPIFLASH_ReadManufactureID		: GD25Q SPIFLASH 读取厂商ID
 @Input				void
 @Return				厂商ID
**********************************************************************************************************/
u32 GD25Q_SPIFLASH_ReadManufactureID(void)
{
	u32 manufactureID = 0;
	
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_ManufactDeviceID);
	GD25Q_SPI_FLASH_SendByte(0x00);
	GD25Q_SPI_FLASH_SendByte(0x00);
	GD25Q_SPI_FLASH_SendByte(0x00);
	manufactureID |= GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte) << 8;
	manufactureID |= GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return manufactureID;
}

/**********************************************************************************************************
 @Function			u32 GD25Q_SPIFLASH_ReadIdentificationID(void)
 @Description			GD25Q_SPIFLASH_ReadIdentificationID	: GD25Q SPIFLASH 读取型号ID
 @Input				void
 @Return				型号ID
**********************************************************************************************************/
u32 GD25Q_SPIFLASH_ReadIdentificationID(void)
{
	u32 identificationID = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
	
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_JedecDeviceID);
	Temp0 = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	Temp1 = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	Temp2 = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	identificationID = (Temp0 << 16) | (Temp1 << 8) | Temp2;
	
	return identificationID;
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteEnable(void)
 @Description			GD25Q_SPIFLASH_WriteEnable	: GD25Q SPIFLASH 写使能
 @Input				void
 @Return				void
 @attention			WEL置位
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteEnable(void)
{
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_WriteEnable);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteDisable(void)
 @Description			GD25Q_SPIFLASH_WriteDisable	: GD25Q SPIFLASH 写禁止
 @Input				void
 @Return				void
 @attention			WEL清零
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteDisable(void)
{
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_WriteDisable);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			u8 GD25Q_SPIFLASH_ReadStatusRegister(u8 statusRegister)
 @Description			GD25Q_SPIFLASH_ReadStatusRegister	: GD25Q SPIFLASH 读状态寄存器
 @Input				状态寄存器地址
 @Return				状态寄存器值
**********************************************************************************************************/
u8 GD25Q_SPIFLASH_ReadStatusRegister(u8 statusRegister)
{
	u8 readByte = 0;
	
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(statusRegister);
	readByte = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return readByte;
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteStatusRegister(u8 srLow, u8 srHigh)
 @Description			GD25Q_SPIFLASH_WriteStatusRegister	: GD25Q SPIFLASH 写状态寄存器
 @Input				srLow						: 状态寄存器低字节
					srHigh						: 状态寄存器高字节
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteStatusRegister(u8 srLow, u8 srHigh)
{
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	GD25Q_SPI_FLASH_SendByte(GD25Q_WriteStatusReg);
	GD25Q_SPI_FLASH_SendByte(srLow);
	GD25Q_SPI_FLASH_SendByte(srHigh);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WaitForBusy(void)
 @Description			GD25Q_SPIFLASH_WaitForBusy		: GD25Q SPIFLASH 等待设备空闲
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_WaitForBusy(void)
{
	u8 flashStatus = 0;
	
	/* 选择SPI FLASH, NSS使能 */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* Send "Read Status Register" instruction */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReadStatusReg1);
	
	/* Loop as long as the memory is busy with a write cycle */
	do {
		flashStatus = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
	}
	while ((flashStatus & 0x01) == 0x01);
	
	/* 禁用SPI FLASH, NSS失能 */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_PowerDown(void)
 @Description			GD25Q_SPIFLASH_PowerDown			: GD25Q SPIFLASH 进入掉电模式
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_PowerDown(void)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* Send "Power Down" instruction */
	GD25Q_SPI_FLASH_SendByte(GD25Q_PowerDown);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* Wait for TDP */
	Delay_US(3);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WakeUp(void)
 @Description			GD25Q_SPIFLASH_WakeUp			: GD25Q SPIFLASH 唤醒
 @Input				void
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_WakeUp(void)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* Send "Release Power Down" instruction */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReleasePowerDown);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* Wait for TRES1 */
	Delay_US(5);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_EraseChip(void)
 @Description			GD25Q_SPIFLASH_EraseChip			: GD25Q SPIFLASH 擦除Chip
 @Input				void
 @Return				void
 @attention			800MS
**********************************************************************************************************/
void GD25Q_SPIFLASH_EraseChip(void)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 发送FLASH写使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空闲 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 发送片擦除命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ChipErase);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待擦除完毕 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_EraseBlock(u32 BlockAddr)
 @Description			GD25Q_SPIFLASH_EraseBlock		: GD25Q SPIFLASH 擦除Block
 @Input				BlockAddr						: 块地址(0x10000倍数)
 @Return				void
 @attention			GD25Q80CSIG SPI FLASH 擦除块大小为64KB(65536Byte),即一个块区大小,在写入数据之前要求先擦除空间
					50MS
**********************************************************************************************************/
void GD25Q_SPIFLASH_EraseBlock(u32 BlockAddr)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 发送FLASH写使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空闲 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 发送块区擦除命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_BlockErase);
	
	/* 发送块区擦除地址高位 */
	GD25Q_SPI_FLASH_SendByte((BlockAddr & 0xFF0000) >> 16);
	
	/* 发送块区擦除地址中位 */
	GD25Q_SPI_FLASH_SendByte((BlockAddr & 0xFF00) >> 8);
	
	/* 发送块区擦除地址低位 */
	GD25Q_SPI_FLASH_SendByte(BlockAddr & 0xFF);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待擦除完毕 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_EraseSector(u32 SectorAddr)
 @Description			GD25Q_SPIFLASH_EraseSector		: GD25Q SPIFLASH 擦除Sector
 @Input				SectorAddr					: 扇区地址(0x1000倍数)
 @Return				void
 @attention			GD25Q80CSIG SPI FLASH 最小擦除块大小为4KB(4096Byte),即一个扇区大小,在写入数据之前要求先擦除空间
					20MS
**********************************************************************************************************/
void GD25Q_SPIFLASH_EraseSector(u32 SectorAddr)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 发送FLASH写使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空闲 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 发送扇区擦除命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_SectorErase);
	
	/* 发送扇区擦除地址高位 */
	GD25Q_SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
	
	/* 发送扇区擦除地址中位 */
	GD25Q_SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
	
	/* 发送扇区擦除地址低位 */
	GD25Q_SPI_FLASH_SendByte(SectorAddr & 0xFF);
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待擦除完毕 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_ReadBuffer(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
 @Description			GD25Q_SPIFLASH_ReadBuffer		: GD25Q SPIFLASH 读取SPI FLASH数据
 @Input				pBuffer						: 数据存储区
					ReadAddr						: 数据读取地址
					NumByteToRead					: 读取数据长度
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_ReadBuffer(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 发送读指令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReadData);
	
	/* 发送读地址高位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
	
	/* 发送读地址中位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);
	
	/* 发送读地址低位 */
	GD25Q_SPI_FLASH_SendByte(ReadAddr & 0xFF);
	
	/* 读取数据 */
	while (NumByteToRead--) {
		*pBuffer = GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte);
		pBuffer++;
	}
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WritePage(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
 @Description			GD25Q_SPIFLASH_WritePage			: GD25Q SPIFLASH 写入SPI FLASH数据Page
 @Input				pBuffer						: 数据存储区
					WriteAddr						: 数据写入地址
					NumByteToWrite					: 写入数据长度
 @Return				void
 @attention			写入字节数不得超过该页写入剩余字节数
**********************************************************************************************************/
void GD25Q_SPIFLASH_WritePage(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
#ifdef GD25Q_80CSIG
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	/* 发送FLASH写使能命令 */
	GD25Q_SPIFLASH_WriteEnable();
	
	/* 等待FLASH空闲 */
	GD25Q_SPIFLASH_WaitForBusy();
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 发送页写命令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_PageProgram);
	
	/* 发送写地址高位 */
	GD25Q_SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
	
	/* 发送写地址中位 */
	GD25Q_SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
	
	/* 发送写地址低位 */
	GD25Q_SPI_FLASH_SendByte(WriteAddr & 0xFF);
	
	/* 写入数据 */
	while (NumByteToWrite--) {
		GD25Q_SPI_FLASH_SendByte(*pBuffer);
		pBuffer++;
	}
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	/* 等待写入完毕 */
	GD25Q_SPIFLASH_WaitForBusy();
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_WriteBuffer(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
 @Description			GD25Q_SPIFLASH_WriteBuffer		: GD25Q SPIFLASH 写入SPI FLASH数据
 @Input				pBuffer						: 数据存储区
					WriteAddr						: 数据写入地址
					NumByteToWrite					: 写入数据长度
 @Return				void
 @attention			具有自动换页功能
**********************************************************************************************************/
void GD25Q_SPIFLASH_WriteBuffer(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
{
#ifdef GD25Q_80CSIG
	u16 pagereMain;
	
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return;
	}
	
	pagereMain = GD25Q80_PAGE_BYTE_SIZE - WriteAddr % GD25Q80_PAGE_BYTE_SIZE;
	if (NumByteToWrite <= pagereMain) pagereMain = NumByteToWrite;
	
	while (true) {
		GD25Q_SPIFLASH_WritePage(pBuffer, WriteAddr, pagereMain);
		if (NumByteToWrite == pagereMain) break;
		else {
			pBuffer += pagereMain;
			WriteAddr += pagereMain;
			
			NumByteToWrite -= pagereMain;
			if (NumByteToWrite > GD25Q80_PAGE_BYTE_SIZE) pagereMain = GD25Q80_PAGE_BYTE_SIZE;
			else pagereMain = NumByteToWrite;
		}
	}
#endif
}

/**********************************************************************************************************
 @Function			unsigned char GD25Q_SPIFLASH_GetByte(u32 ReadAddr)
 @Description			GD25Q_SPIFLASH_GetByte						: GD25Q SPIFLASH 读取1个Byte
 @Input				void
 @Return				val
**********************************************************************************************************/
unsigned char GD25Q_SPIFLASH_GetByte(u32 ReadAddr)
{
#ifdef GD25Q_80CSIG
	unsigned char val = 0;
	
	GD25Q_SPIFLASH_ReadBuffer(&val, ReadAddr, 1);
	
	return val;
#endif
}

/**********************************************************************************************************
 @Function			unsigned short GD25Q_SPIFLASH_GetHalfWord(u32 ReadAddr)
 @Description			GD25Q_SPIFLASH_GetHalfWord					: GD25Q SPIFLASH 读取2个Byte
 @Input				void
 @Return				val
**********************************************************************************************************/
unsigned short GD25Q_SPIFLASH_GetHalfWord(u32 ReadAddr)
{
#ifdef GD25Q_80CSIG
	unsigned short val = 0;
	unsigned char tmpval[2];
	
	GD25Q_SPIFLASH_ReadBuffer(tmpval, ReadAddr, 2);
	
	val |= tmpval[0];
	val |= tmpval[1] << 8;
	
	return val;
#endif
}

/**********************************************************************************************************
 @Function			unsigned int GD25Q_SPIFLASH_GetWord(u32 ReadAddr)
 @Description			GD25Q_SPIFLASH_GetWord						: GD25Q SPIFLASH 读取4个Byte
 @Input				void
 @Return				val
**********************************************************************************************************/
unsigned int GD25Q_SPIFLASH_GetWord(u32 ReadAddr)
{
#ifdef GD25Q_80CSIG
	unsigned int val = 0;
	unsigned char tmpval[4];
	
	GD25Q_SPIFLASH_ReadBuffer(tmpval, ReadAddr, 4);
	
	val |= tmpval[0];
	val |= tmpval[1] << 8;
	val |= tmpval[2] << 16;
	val |= tmpval[3] << 24;
	
	return val;
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_SetByte(u32 WriteAddr, unsigned char val)
 @Description			GD25Q_SPIFLASH_SetByte						: GD25Q SPIFLASH 写入1个Byte
 @Input				val
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_SetByte(u32 WriteAddr, unsigned char val)
{
#ifdef GD25Q_80CSIG
	GD25Q_SPIFLASH_WriteBuffer(&val, WriteAddr, 1);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_SetHalfWord(u32 WriteAddr, unsigned short val)
 @Description			GD25Q_SPIFLASH_SetHalfWord					: GD25Q SPIFLASH 写入2个Byte
 @Input				val
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_SetHalfWord(u32 WriteAddr, unsigned short val)
{
#ifdef GD25Q_80CSIG
	unsigned char tmpval[2];
	
	tmpval[0] = val & 0xFF;
	tmpval[1] = (val >> 8) & 0xFF;
	
	GD25Q_SPIFLASH_WriteBuffer(tmpval, WriteAddr, 2);
#endif
}

/**********************************************************************************************************
 @Function			void GD25Q_SPIFLASH_SetWord(u32 WriteAddr, unsigned int val)
 @Description			GD25Q_SPIFLASH_SetWord						: GD25Q SPIFLASH 写入4个Byte
 @Input				val
 @Return				void
**********************************************************************************************************/
void GD25Q_SPIFLASH_SetWord(u32 WriteAddr, unsigned int val)
{
#ifdef GD25Q_80CSIG
	unsigned char tmpval[4];
	
	tmpval[0] = val & 0xFF;
	tmpval[1] = (val >> 8) & 0xFF;
	tmpval[2] = (val >> 16) & 0xFF;
	tmpval[3] = (val >> 24) & 0xFF;
	
	GD25Q_SPIFLASH_WriteBuffer(tmpval, WriteAddr, 4);
#endif
}

/**********************************************************************************************************
 @Function			unsigned int GD25Q_SPIFLASH_GetNumofByte(u32 ReadAddr, u16 AllNum, u8 ByteVal)
 @Description			GD25Q_SPIFLASH_GetNumofByte					: GD25Q SPIFLASH 读取指定地址中指定字节中有该值的个数
 @Input				ReadAddr									: 读取地址
					AllNum									: 读取字节数
					ByteVal									: 匹配值
 @Return				val
**********************************************************************************************************/
unsigned int GD25Q_SPIFLASH_GetNumofByte(u32 ReadAddr, u16 AllNum, u8 ByteVal)
{
#ifdef GD25Q_80CSIG
	unsigned int ReadByteval = 0;
	
	if (GD25Q80CSIG_OK != GD25Q_SPIFLASH_Get_Status()) {
		return 0;
	}
	
	/* Select the FLASH: Chip Select low */
	GD25Q_FLASH_SPIx_NSS_ENABLE();
	
	/* 发送读指令 */
	GD25Q_SPI_FLASH_SendByte(GD25Q_ReadData);
	
	/* 发送读地址高位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
	
	/* 发送读地址中位 */
	GD25Q_SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);
	
	/* 发送读地址低位 */
	GD25Q_SPI_FLASH_SendByte(ReadAddr & 0xFF);
	
	/* 读取数据 */
	while (AllNum--) {
		if (ByteVal == GD25Q_SPI_FLASH_SendByte(GD25Q_Dummy_Byte)) {
			ReadByteval++;
		}
	}
	
	/* Deselect the FLASH: Chip Select high */
	GD25Q_FLASH_SPIx_NSS_DISABLE();
	
	return ReadByteval;
#endif
}

/********************************************** END OF FLEE **********************************************/
#ifndef __HAL_SPI_FLASH_H
#define   __HAL_SPI_FLASH_H

#include "sys.h"

#define GD25Q80CSIGDeviceID						0x13
#define GD25Q80CSIGManufactureID					0xC813
#define GD25Q80CSIGIdentificationID				0xC84014

#define GD25Q40BSIGDeviceID						0x12
#define GD25Q40BSIGManufactureID					0xC812
#define GD25Q40BSIGIdentificationID				0xC84013

#define GD25Q80_BASE_ADDR						0x000000U
#define GD25Q80_CHIP_BYTE_SIZE					0x100000U													// 1 M
#define GD25Q80_BLOCK_BYTE_SIZE					0x010000U													//64 K
#define GD25Q80_SECTOR_BYTE_SIZE					0x001000U													// 4 K
#define GD25Q80_PAGE_BYTE_SIZE					0x000100U													//256Byte

#define GD25Q80_BLOCK_ADDRESS0					0x000000U
#define GD25Q80_BLOCK_ADDRESS1					0x010000U
#define GD25Q80_BLOCK_ADDRESS2					0x020000U
#define GD25Q80_BLOCK_ADDRESS3					0x030000U
#define GD25Q80_BLOCK_ADDRESS4					0x040000U
#define GD25Q80_BLOCK_ADDRESS5					0x050000U
#define GD25Q80_BLOCK_ADDRESS6					0x060000U
#define GD25Q80_BLOCK_ADDRESS7					0x070000U
#define GD25Q80_BLOCK_ADDRESS8					0x080000U
#define GD25Q80_BLOCK_ADDRESS9					0x090000U
#define GD25Q80_BLOCK_ADDRESS10					0x0A0000U
#define GD25Q80_BLOCK_ADDRESS11					0x0B0000U
#define GD25Q80_BLOCK_ADDRESS12					0x0C0000U
#define GD25Q80_BLOCK_ADDRESS13					0x0D0000U
#define GD25Q80_BLOCK_ADDRESS14					0x0E0000U
#define GD25Q80_BLOCK_ADDRESS15					0x0F0000U

#define GD25Q80_SECTOR_ADDRESS(nSector)				(GD25Q80_BASE_ADDR + (GD25Q80_SECTOR_BYTE_SIZE * nSector))
#define GD25Q80_PAGE_ADDRESS(nPage)				(GD25Q80_BASE_ADDR + (GD25Q80_PAGE_BYTE_SIZE * nPage))

#define GD25Q80_SECTOR_NUM						256
#define GD25Q80_PAGE_NUM							4096

#define APP_PACKSLICE_NUM						300														//升级APP分片最大分片数

/* APP1 FLASH ADDRESS TABLE */
#define APP1_BASE_ADDR							0x000000U
#define APP1_BYTE_SIZE							0x040000U
#define APP1_INFORMATION_ADDR						APP1_BASE_ADDR
#define APP1_INFORMATION_SIZE						0x1000
#define APP1_DATA_ADDR							APP1_BASE_ADDR + APP1_INFORMATION_SIZE
#define APP1_DATA_SIZE							APP1_BYTE_SIZE - APP1_INFORMATION_SIZE
#define APP1_INFO_UPGRADE_STATUS_OFFSET				APP1_INFORMATION_ADDR
#define APP1_INFO_UPGRADE_STATUS_LENGTH				1														//升级标志 高4位0x5(0101)有升级包 低4位0x5(0101)可升级
#define APP1_INFO_UPGRADE_BASEADDR_OFFSET			APP1_INFO_UPGRADE_STATUS_OFFSET + APP1_INFO_UPGRADE_STATUS_LENGTH
#define APP1_INFO_UPGRADE_BASEADDR_LENGTH			4														//升级APP起始地址
#define APP1_INFO_UPGRADE_BLOCKNUM_OFFSET			APP1_INFO_UPGRADE_BASEADDR_OFFSET + APP1_INFO_UPGRADE_BASEADDR_LENGTH
#define APP1_INFO_UPGRADE_BLOCKNUM_LENGTH			2														//升级APP存放块数
#define APP1_INFO_UPGRADE_BLOCKLEN_OFFSET			APP1_INFO_UPGRADE_BLOCKNUM_OFFSET + APP1_INFO_UPGRADE_BLOCKNUM_LENGTH
#define APP1_INFO_UPGRADE_BLOCKLEN_LENGTH			2														//升级APP块长度
#define APP1_INFO_UPGRADE_DATALEN_OFFSET			APP1_INFO_UPGRADE_BLOCKLEN_OFFSET + APP1_INFO_UPGRADE_BLOCKLEN_LENGTH
#define APP1_INFO_UPGRADE_DATALEN_LENGTH			2														//升级APP块有效长度
#define APP1_INFO_UPGRADE_INDEX_OFFSET				APP1_INFO_UPGRADE_DATALEN_OFFSET + APP1_INFO_UPGRADE_DATALEN_LENGTH
#define APP1_INFO_UPGRADE_INDEX_LENGTH				4														//升级APP序号
#define APP1_INFO_UPGRADE_SOFTVER_OFFSET			APP1_INFO_UPGRADE_INDEX_OFFSET + APP1_INFO_UPGRADE_INDEX_LENGTH
#define APP1_INFO_UPGRADE_SOFTVER_LENGTH			4														//升级包版本号 高2字节主版本号 低2字节从版本号
#define APP1_INFO_DOWNLOAD_TIME_OFFSET				APP1_INFO_UPGRADE_SOFTVER_OFFSET + APP1_INFO_UPGRADE_SOFTVER_LENGTH
#define APP1_INFO_DOWNLOAD_TIME_LENGTH				4														//升级包下载时间
#define APP1_DATA_CHECK_CODE_OFFSET				APP1_INFO_DOWNLOAD_TIME_OFFSET + APP1_INFO_DOWNLOAD_TIME_LENGTH
#define APP1_DATA_CHECK_CODE_LENGTH				4														//升级包校验码
#define APP1_PACKSLICE_STATUS_OFFSET				APP1_DATA_CHECK_CODE_OFFSET + APP1_DATA_CHECK_CODE_LENGTH
#define APP1_PACKSLICE_STATUS_LENGTH				APP_PACKSLICE_NUM											//升级包分片下载状态(0x00有 0xFF无)
/* END APP1 ADDRESS TABLE */

/* APP2 FLASH ADDRESS TABLE */
#define APP2_BASE_ADDR							0x040000U
#define APP2_BYTE_SIZE							0x040000U
#define APP2_INFORMATION_ADDR						APP2_BASE_ADDR
#define APP2_INFORMATION_SIZE						0x1000
#define APP2_DATA_ADDR							APP2_BASE_ADDR + APP2_INFORMATION_SIZE
#define APP2_DATA_SIZE							APP2_BYTE_SIZE - APP2_INFORMATION_SIZE
#define APP2_INFO_UPGRADE_STATUS_OFFSET				APP2_INFORMATION_ADDR
#define APP2_INFO_UPGRADE_STATUS_LENGTH				1														//升级标志 高4位0x5(0101)有升级包 低4位0x5(0101)可升级
#define APP2_INFO_UPGRADE_BASEADDR_OFFSET			APP2_INFO_UPGRADE_STATUS_OFFSET + APP2_INFO_UPGRADE_STATUS_LENGTH
#define APP2_INFO_UPGRADE_BASEADDR_LENGTH			4														//升级APP起始地址
#define APP2_INFO_UPGRADE_BLOCKNUM_OFFSET			APP2_INFO_UPGRADE_BASEADDR_OFFSET + APP2_INFO_UPGRADE_BASEADDR_LENGTH
#define APP2_INFO_UPGRADE_BLOCKNUM_LENGTH			2														//升级APP存放块数
#define APP2_INFO_UPGRADE_BLOCKLEN_OFFSET			APP2_INFO_UPGRADE_BLOCKNUM_OFFSET + APP2_INFO_UPGRADE_BLOCKNUM_LENGTH
#define APP2_INFO_UPGRADE_BLOCKLEN_LENGTH			2														//升级APP块长度
#define APP2_INFO_UPGRADE_DATALEN_OFFSET			APP2_INFO_UPGRADE_BLOCKLEN_OFFSET + APP2_INFO_UPGRADE_BLOCKLEN_LENGTH
#define APP2_INFO_UPGRADE_DATALEN_LENGTH			2														//升级APP块有效长度
#define APP2_INFO_UPGRADE_INDEX_OFFSET				APP2_INFO_UPGRADE_DATALEN_OFFSET + APP2_INFO_UPGRADE_DATALEN_LENGTH
#define APP2_INFO_UPGRADE_INDEX_LENGTH				4														//升级APP序号
#define APP2_INFO_UPGRADE_SOFTVER_OFFSET			APP2_INFO_UPGRADE_INDEX_OFFSET + APP2_INFO_UPGRADE_INDEX_LENGTH
#define APP2_INFO_UPGRADE_SOFTVER_LENGTH			4														//升级包版本号 高2字节主版本号 低2字节从版本号
#define APP2_INFO_DOWNLOAD_TIME_OFFSET				APP2_INFO_UPGRADE_SOFTVER_OFFSET + APP2_INFO_UPGRADE_SOFTVER_LENGTH
#define APP2_INFO_DOWNLOAD_TIME_LENGTH				4														//升级包下载时间
#define APP2_DATA_CHECK_CODE_OFFSET				APP2_INFO_DOWNLOAD_TIME_OFFSET + APP2_INFO_DOWNLOAD_TIME_LENGTH
#define APP2_DATA_CHECK_CODE_LENGTH				4														//升级包校验码
#define APP2_PACKSLICE_STATUS_OFFSET				APP2_DATA_CHECK_CODE_OFFSET + APP2_DATA_CHECK_CODE_LENGTH
#define APP2_PACKSLICE_STATUS_LENGTH				APP_PACKSLICE_NUM											//升级包分片下载状态(0x00有 0xFF无)
/* END APP2 ADDRESS TABLE */

/* Definition for SPIx clock resources */
#define GD25Q_FLASH_SPIx							SPI1
#define GD25Q_FLASH_SPIx_RCC_CLK_ENABLE()			__HAL_RCC_SPI1_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_RCC_CLK_DISABLE()			__HAL_RCC_SPI1_CLK_DISABLE()

#define GD25Q_FLASH_SPIx_FORCE_RESET()				__HAL_RCC_SPI1_FORCE_RESET()
#define GD25Q_FLASH_SPIx_RELEASE_RESET()			__HAL_RCC_SPI1_RELEASE_RESET()

/* Definition for SPIx GPIO resources */
#define GD25Q_FLASH_SPIx_NSS_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOB_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_NSS_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOB_CLK_DISABLE()
#define GD25Q_FLASH_SPIx_SCK_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOA_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_SCK_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOA_CLK_DISABLE()
#define GD25Q_FLASH_SPIx_MOSI_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOA_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_MOSI_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOA_CLK_DISABLE()
#define GD25Q_FLASH_SPIx_MISO_GPIO_CLK_ENABLE()		__HAL_RCC_GPIOA_CLK_ENABLE()
#define GD25Q_FLASH_SPIx_MISO_GPIO_CLK_DISABLE()		__HAL_RCC_GPIOA_CLK_DISABLE()

/* Definition for SPIx Pins */
#define GD25Q_FLASH_SPIx_NSS_GPIO_PORT				GPIOB
#define GD25Q_FLASH_SPIx_NSS_PIN					GPIO_PIN_12
#define GD25Q_FLASH_SPIx_SCK_GPIO_PORT				GPIOA
#define GD25Q_FLASH_SPIx_SCK_PIN					GPIO_PIN_5
#define GD25Q_FLASH_SPIx_SCK_AF					GPIO_AF5_SPI1
#define GD25Q_FLASH_SPIx_MOSI_GPIO_PORT				GPIOA
#define GD25Q_FLASH_SPIx_MOSI_PIN					GPIO_PIN_7
#define GD25Q_FLASH_SPIx_MOSI_AF					GPIO_AF5_SPI1
#define GD25Q_FLASH_SPIx_MISO_GPIO_PORT				GPIOA
#define GD25Q_FLASH_SPIx_MISO_PIN					GPIO_PIN_6
#define GD25Q_FLASH_SPIx_MISO_AF					GPIO_AF5_SPI1

#define GD25Q_FLASH_SPIx_NSS_ENABLE()				HAL_GPIO_WritePin(GD25Q_FLASH_SPIx_NSS_GPIO_PORT, GD25Q_FLASH_SPIx_NSS_PIN, GPIO_PIN_RESET)
#define GD25Q_FLASH_SPIx_NSS_DISABLE()				HAL_GPIO_WritePin(GD25Q_FLASH_SPIx_NSS_GPIO_PORT, GD25Q_FLASH_SPIx_NSS_PIN, GPIO_PIN_SET)

#define GD25Q_Dummy_Byte							0xFF

/* GD25Q80CSIG 指令表 */
#define GD25Q_WriteEnable						0x06
#define GD25Q_WriteDisable						0x04

#define GD25Q_ReadStatusReg1						0x05
#define GD25Q_ReadStatusReg2						0x35
#define GD25Q_WriteStatusReg						0x01

#define GD25Q_ReadData							0x03
#define GD25Q_FastReadData						0x0B
#define GD25Q_FastReadDual						0x3B
#define GD25Q_PageProgram						0x02

#define GD25Q_SectorErase						0x20
#define GD25Q_BlockErase							0xD8
#define GD25Q_ChipErase							0xC7

#define GD25Q_PowerDown							0xB9
#define GD25Q_ReleasePowerDown					0xAB
#define GD25Q_DeviceID							0xAB
#define GD25Q_ManufactDeviceID					0x90
#define GD25Q_JedecDeviceID						0x9F
/* GD25Q80CSIG End Command */

typedef enum
{
	GD25Q80CSIG_OK								= 0x00,
	GD25Q80CSIG_ERROR							= 0x01
}GD25Q_StatusTypeDef;

extern SPI_HandleTypeDef GD25Q_SPIFLASH_Handler;
extern GD25Q_StatusTypeDef GD25QStatus;

void GD25Q_SPIFLASH_Init(void);														//GD25Q SPIFLASH 初始化
GD25Q_StatusTypeDef GD25Q_SPIFLASH_Get_Status(void);										//GD25Q SPIFLASH 状态

u8 GD25Q_SPI_FLASH_ReadByte(void);														//SPI FLASH 读取一个字节数据
u8 GD25Q_SPI_FLASH_SendByte(u8 byte);													//SPI FLASH 发送一个字节数据

u32 GD25Q_SPIFLASH_ReadDeviceID(void);													//GD25Q SPIFLASH 读取设备ID
u32 GD25Q_SPIFLASH_ReadManufactureID(void);												//GD25Q SPIFLASH 读取厂商ID
u32 GD25Q_SPIFLASH_ReadIdentificationID(void);											//GD25Q SPIFLASH 读取型号ID

void GD25Q_SPIFLASH_WriteEnable(void);													//GD25Q SPIFLASH 写使能
void GD25Q_SPIFLASH_WriteDisable(void);													//GD25Q SPIFLASH 写禁止

u8 GD25Q_SPIFLASH_ReadStatusRegister(u8 statusRegister);									//GD25Q SPIFLASH 读状态寄存器
void GD25Q_SPIFLASH_WriteStatusRegister(u8 srLow, u8 srHigh);								//GD25Q SPIFLASH 写状态寄存器

void GD25Q_SPIFLASH_WaitForBusy(void);													//GD25Q SPIFLASH 等待设备空闲
void GD25Q_SPIFLASH_PowerDown(void);													//GD25Q SPIFLASH 进入掉电模式
void GD25Q_SPIFLASH_WakeUp(void);														//GD25Q SPIFLASH 唤醒

void GD25Q_SPIFLASH_EraseChip(void);													//GD25Q SPIFLASH 擦除Chip
void GD25Q_SPIFLASH_EraseBlock(u32 BlockAddr);											//GD25Q SPIFLASH 擦除Block
void GD25Q_SPIFLASH_EraseSector(u32 SectorAddr);											//GD25Q SPIFLASH 擦除Sector

void GD25Q_SPIFLASH_ReadBuffer(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);					//GD25Q SPIFLASH 读取SPI FLASH数据
void GD25Q_SPIFLASH_WritePage(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);					//GD25Q SPIFLASH 写入SPI FLASH数据Page
void GD25Q_SPIFLASH_WriteBuffer(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite);				//GD25Q SPIFLASH 写入SPI FLASH数据

unsigned char GD25Q_SPIFLASH_GetByte(u32 ReadAddr);										//GD25Q SPIFLASH 读取1个Byte
unsigned short GD25Q_SPIFLASH_GetHalfWord(u32 ReadAddr);									//GD25Q SPIFLASH 读取2个Byte
unsigned int GD25Q_SPIFLASH_GetWord(u32 ReadAddr);										//GD25Q SPIFLASH 读取4个Byte

void GD25Q_SPIFLASH_SetByte(u32 WriteAddr, unsigned char val);								//GD25Q SPIFLASH 写入1个Byte
void GD25Q_SPIFLASH_SetHalfWord(u32 WriteAddr, unsigned short val);							//GD25Q SPIFLASH 写入2个Byte
void GD25Q_SPIFLASH_SetWord(u32 WriteAddr, unsigned int val);								//GD25Q SPIFLASH 写入4个Byte

unsigned int GD25Q_SPIFLASH_GetNumofByte(u32 ReadAddr, u16 AllNum, u8 ByteVal);					//GD25Q SPIFLASH 读取指定地址中指定字节中有该值的个数

#endif /* __HAL_SPI_FLASH_H */

 

STM32H750微控制器中,Quad-SPI(QSPI)接口用于与外部闪存(Flash)通信。初始化QSPI接口以访问外部Quad-SPI闪存(QFlash)需要以下几个步骤: 1. **使能QSPI时钟**: 首先,需要使能QSPI外设的时钟。在STM32H750中,这通常通过RCC(复位和时钟控制)寄存器完成。 2. **配置GPIO引脚**: QSPI接口需要使用特定的GPIO引脚来与外部闪存通信。需要将这些引脚配置为复用功能,并设置为QSPI模式。 3. **初始化QSPI外设**: 配置QSPI外设的参数,包括时钟分频、数据帧格式、闪存大小等。 4. **使能QSPI外设**: 配置完成后,使能QSPI外设。 以下是一个简单的初始化代码示例: ```c #include "stm32h7xx_hal.h" QSPI_HandleTypeDef hqspi; void MX_QUADSPI_Init(void) { /* QSPI外设时钟使能 */ __HAL_RCC_QSPI_CLK_ENABLE(); /* QSPI GPIO引脚配置 */ __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; /* 配置PF10, PF8, PF9, PF7, PF6为QSPI复用功能 */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_7|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); /* 配置PB6为QSPI复用功能 */ GPIO_InitStruct.Pin = GPIO_PIN_6; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* QSPI外设配置 */ hqspi.Instance = QUADSPI; hqspi.Init.ClockPrescaler = 2; hqspi.Init.FifoThreshold = 4; hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; hqspi.Init.FlashSize = 23; hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; if (HAL_QSPI_Init(&hqspi) != HAL_OK) { /* 初始化错误处理 */ Error_Handler(); } } /* QSPI外设初始化错误处理函数 */ void Error_Handler(void) { /* 用户可以添加自己的错误处理代码 */ while(1); } ``` 在这个示例中,我们首先使能了QSPI和相关的GPIO时钟,然后配置了QSPI使用的GPIO引脚。接着,我们初始化了QSPI外设,并配置了相关的参数。最后,我们使能了QSPI外设。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值