代码借鉴自野火骄阳(STM32F407)电机开发板例程中的“14-SPI—读写串行FLASH(W25Q128)”。有以下区别:
1. 芯片由STM32F407换为了STM32F405;
2. SPI Flash由W25Q128换为了W25Q64;
3. 通讯由SPI1改为了SPI2;
4. 模式由Mode 3改为了Mode 0。
相关代码如下:
spi.c
/**
******************************************************************************
* File Name : SPI.c
* Description : This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "spi.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
SPI_HandleTypeDef hspi2;
/* SPI2 init function */
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
}
}
void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
if(spiHandle->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspDeInit 0 */
/* USER CODE END SPI2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI2_CLK_DISABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
/* USER CODE BEGIN SPI2_MspDeInit 1 */
/* USER CODE END SPI2_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
spi.h
/**
******************************************************************************
* File Name : SPI.h
* Description : This file provides code for the configuration
* of the SPI instances.
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __spi_H
#define __spi_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern SPI_HandleTypeDef hspi2;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_SPI2_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ spi_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
bsp_spi_flash.c
#include "bsp_spi_flash.h"
static __IO uint32_t SPITimeout = SPIT_LONG_TIMEOUT;
static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);
void SPI_FLASH_Init(void)
{
__HAL_SPI_ENABLE(&hspi2);
}
/*
* @brief 擦除FLASH扇区
* @param SectorAddr:要擦除的扇区地址
* @retval 无
*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
//发送FLASH写使能命令
SPI_FLASH_WriteEnable();
SPI_FLASH_WaitForWriteEnd();
//擦除扇区
//选择FLASH: CS低电平
SPI_FLASH_CS_LOW();
//发送扇区擦除指令
SPI_FLASH_SendByte(W25X_SECTOR_ERASE);
//发送擦除扇区地址的高位
SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
//发送擦除扇区地址的中位
SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
//发送擦除扇区地址的低位
SPI_FLASH_SendByte(SectorAddr & 0xFF);
//停止信号 FLASH: CS 高电平
SPI_FLASH_CS_HIGH();
//等待擦除完毕
SPI_FLASH_WaitForWriteEnd();
}
/*
* @brief 擦除FLASH扇区,整片擦除
* @param 无
* @retval 无
*/
void SPI_FLASH_BulkErase(void)
{
//发送FLASH写使能命令
SPI_FLASH_WriteEnable();
//整块Erase
//选择FLASH: CS低电平
SPI_FLASH_CS_LOW();
//发送整块擦除指令
SPI_FLASH_SendByte(W25X_CHIP_ERASE);
//停止信号 FLASH: CS 高电平
SPI_FLASH_CS_HIGH();
//等待擦除完毕
SPI_FLASH_WaitForWriteEnd();
}
/*
* @brief 对FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区
* @param pBuffer,要写入数据的指针
* @param WriteAddr,写入地址
* @param NumByteToWrite,写入数据长度,必须小于等于SPI_FLASH_PerWritePageSize
* @retval 无
*/
void SPI_FLASH_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
//发送FLASH写使能命令
SPI_FLASH_WriteEnable();
//选择FLASH: CS低电平
SPI_FLASH_CS_LOW();
//写页写指令
SPI_FLASH_SendByte(W25X_PAGE_PROGRAM); //#define W25X_PAGE_PROGRAM 0x02
//发送写地址的高位
SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
//发送写地址的中位
SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
//发送写地址的低位
SPI_FLASH_SendByte(WriteAddr & 0xFF);
if(NumByteToWrite > SPI_FLASH_PerWritePageSize)
{
NumByteToWrite = SPI_FLASH_PerWritePageSize;
FLASH_ERROR("SPI_FLASH_PageWrite too large!");
}
//写入数据
while(NumByteToWrite--)
{
//发送当前要写入的字节数据
//SPI_FLASH_SendByte(*pBuffer);
//指向下一字节数据
//pBuffer++;
SPI_FLASH_SendByte(*pBuffer++);
}
//停止信号 FLASH: CS 高电平
SPI_FLASH_CS_HIGH();
//等待写入完毕
SPI_FLASH_WaitForWriteEnd();
}
/*
* @brief 对FLASH写入数据,调用本函数写入数据前需要先擦除扇区
* @param pBuffer,要写入数据的指针
* @param WriteAddr,写入地址
* @param NumByteToWrite,写入数据长度
* @retval 无
*/
void SPI_FLASH_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
//mod运算求余,若writeAddr是SPI_FLASH_PageSize整数倍,运算结果Addr值为0
Addr = WriteAddr % SPI_FLASH_PageSize;
//差count个数据值,刚好可以对齐到页地址
count = SPI_FLASH_PageSize - Addr;
//计算出要写多少整数页
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
//mod运算求余,计算出剩余不满一页的字节数
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
//Addr=0,则WriteAddr 刚好按页对齐 aligned
if(Addr == 0)
{
//NumByteToWrite < SPI_FLASH_PageSize
if(NumOfPage == 0)
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
else //NumByteToWrite > SPI_FLASH_PageSize
{
//先把整数页都写了
while(NumOfPage--)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
//若有多余的不满一页的数据,把它写完
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
//若地址与 SPI_FLASH_PageSize 不对齐
else
{
//NumByteToWrite < SPI_FLASH_PageSize
if(NumOfPage == 0)
{
//当前页剩余的count个位置比NumOfSingle小,写不完
if(NumOfSingle > count)
{
temp = NumOfSingle - count;
//先写满当前页
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
//再写剩余的数据
SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
}
//当前页剩余的count个位置能写完NumOfSingle个数据
else
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
//NumByteToWrite > SPI_FLASH_PageSize
else
{
//地址不对齐多出的count分开处理,不加入这个运算
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
//先写满当前页
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
//再把整数页都写了
while(NumOfPage--)
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
WriteAddr += SPI_FLASH_PageSize;
pBuffer += SPI_FLASH_PageSize;
}
//若有多余的不满一页的数据,把它写完
if(NumOfSingle != 0)
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
/*
* @brief 读取FLASH ID
* @param 无
* @retval FLASH ID
*/
uint32_t SPI_FLASH_ReadID(void)
{
uint32_t temp = 0, temp0 = 0, temp1 = 0, temp2 = 0;
//开始通讯:CS低电平
SPI_FLASH_CS_LOW();
//发送JEDEC指令,读取ID
SPI_FLASH_SendByte(W25X_JEDEC_DEVICE_ID); //#define W25X_JEDEC_DEVICE_ID 0x9F
//读取一个字节数据
temp0 = SPI_FLASH_SendByte(Dummy_Byte);
//读取一个字节数据
temp1 = SPI_FLASH_SendByte(Dummy_Byte);
//读取一个字节数据
temp2 = SPI_FLASH_SendByte(Dummy_Byte);
//停止通讯:CS高电平
SPI_FLASH_CS_HIGH();
//把数据组合起来,作为函数的返回值
temp = (temp0 << 16) | (temp1 << 8) | temp2;
return temp;
}
/*
* @brief 读取FLASH Device ID
* @param 无
* @retval FLASH Device ID
*/
uint32_t SPI_FLASH_ReadDeviceID(void)
{
uint32_t temp = 0;
//Select the FLASH: Chip Select low
SPI_FLASH_CS_LOW();
//HAL_Delay(100);
//Send "RDID " instruction
SPI_FLASH_SendByte(W25X_DEVICE_ID); //#define W25X_DEVICE_ID 0xAB
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
//Read a byte from the FLASH
temp = SPI_FLASH_SendByte(Dummy_Byte);
//Deselect the FLASH: Chip Select high
SPI_FLASH_CS_HIGH();
return temp;
}
/*
* @brief 读取FLASH数据
* @param pBuffer,存储读出数据的指针
* @param ReadAddr,读取地址
* @param NumByteToRead,读取数据长度
* @retval 无
*/
void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
//选择FLASH: CS低电平
SPI_FLASH_CS_LOW();
//发送 读 指令
SPI_FLASH_SendByte(W25X_READ_DATA);
//发送 读 地址高位
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
//发送 读 地址中位
SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);
//发送 读 地址低位
SPI_FLASH_SendByte(ReadAddr & 0xFF);
//读取数据
while(NumByteToRead--)
{
//读取一个字节
//*pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
//指向下一个字节缓冲区
//pBuffer++;
*pBuffer++ = SPI_FLASH_SendByte(Dummy_Byte);
}
//停止信号 FLASH: CS 高电平
SPI_FLASH_CS_HIGH();
}
/*******************************************************************************
* Function Name : SPI_FLASH_StartReadSequence
* Description : Initiates a read data byte (READ) sequence from the Flash.
* This is done by driving the /CS line low to select the device,
* then the READ instruction is transmitted followed by 3 bytes
* address. This function exit and keep the /CS line low, so the
* Flash still being selected. With this technique the whole
* content of the Flash is read with a single READ instruction.
* Input : - ReadAddr : FLASH's internal address to read from.
* Output : None
* Return : None
*******************************************************************************/
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr)
{
//Select the FLASH: Chip Select low
SPI_FLASH_CS_LOW();
//Send "Read from Memory " instruction
SPI_FLASH_SendByte(W25X_READ_DATA);
//Send the 24-bit address of the address to read from
//Send ReadAddr high nibble address byte
SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
//Send ReadAddr medium nibble address byte
SPI_FLASH_SendByte((ReadAddr & 0xFF00) >> 8);
//Send ReadAddr low nibble address byte
SPI_FLASH_SendByte(ReadAddr & 0xFF);
}
/*
* @brief 使用SPI读取一个字节的数据
* @param 无
* @retval 返回接收到的数据
*/
uint8_t SPI_FLASH_ReadByte(void)
{
return (SPI_FLASH_SendByte(Dummy_Byte));
}
/**-----------------------------------------------------------------
* @函数名 SPI_FLASH_SendByte
* @功能 通过SPI总线发送一个字节数据(顺便接收一个字节数据)
* Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* @参数 要写入的一个字节数据
* @返回值 在发数据时,MISO信号线上接收的一个字节
***----------------------------------------------------------------*/
uint8_t SPI_FLASH_SendByte(uint8_t TxData)
{
uint8_t Rxdata;
HAL_SPI_TransmitReceive(&hspi2, &TxData, &Rxdata, 1, 1000);
return Rxdata;
}
/*
* @brief 使用SPI发送一个字节的数据
* @param byte:要发送的数据
* @retval 返回接收到的数据
*/
/*uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
SPITimeout = SPIT_FLAG_TIMEOUT;
//等待发送缓冲区为空,TXE事件
while (__HAL_SPI_GET_FLAG( &hspi2, SPI_FLAG_TXE ) == RESET)
{
if((SPITimeout--) == 0)
return SPI_TIMEOUT_UserCallback(0);
}
//写入数据寄存器,把要写入的数据写入发送缓冲区
WRITE_REG(hspi2.Instance->DR, byte);
SPITimeout = SPIT_FLAG_TIMEOUT;
//等待接收缓冲区非空,RXNE事件
while (__HAL_SPI_GET_FLAG( &hspi2, SPI_FLAG_RXNE ) == RESET)
{
if((SPITimeout--) == 0)
return SPI_TIMEOUT_UserCallback(1);
}
//读取数据寄存器,获取接收缓冲区数据
return READ_REG(hspi2.Instance->DR);
}*/
/*******************************************************************************
* Function Name : SPI_FLASH_SendHalfWord
* Description : Sends a Half Word through the SPI interface and return the
* Half Word received from the SPI bus.
* Input : Half Word : Half Word to send.
* Output : None
* Return : The value of the received Half Word.
*******************************************************************************/
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord)
{
SPITimeout = SPIT_FLAG_TIMEOUT;
//Loop while DR register in not emplty
while (__HAL_SPI_GET_FLAG( &hspi2, SPI_FLAG_TXE ) == RESET)
{
if((SPITimeout--) == 0)
return SPI_TIMEOUT_UserCallback(2);
}
//Send Half Word through the SPIx peripheral
WRITE_REG(hspi2.Instance->DR, HalfWord);
SPITimeout = SPIT_FLAG_TIMEOUT;
//Wait to receive a Half Word
while (__HAL_SPI_GET_FLAG( &hspi2, SPI_FLAG_RXNE ) == RESET)
{
if((SPITimeout--) == 0)
return SPI_TIMEOUT_UserCallback(3);
}
//Return the Half Word read from the SPI bus
return READ_REG(hspi2.Instance->DR);
}
/*
* @brief 向FLASH发送 写使能 命令
* @param none
* @retval none
*/
void SPI_FLASH_WriteEnable(void)
{
//通讯开始:CS低
SPI_FLASH_CS_LOW();
//发送写使能命令
SPI_FLASH_SendByte(W25X_WRITE_ENABLE);
//通讯结束:CS高
SPI_FLASH_CS_HIGH();
}
/*
* @brief 向FLASH发送 写禁止 命令
* @param none
* @retval none
*/
void SPI_FLASH_WriteDisable(void)
{
//通讯开始:CS低
SPI_FLASH_CS_LOW();
//发送写禁止命令
SPI_FLASH_SendByte(W25X_WRITE_DISABLE);
//通讯结束:CS高
SPI_FLASH_CS_HIGH();
}
/*
* @brief 等待WIP(BUSY)标志被置0,即等待到FLASH内部数据写入完毕
* @param none
* @retval none
*/
void SPI_FLASH_WaitForWriteEnd(void)
{
uint8_t flash_Status = 0;
//选择 FLASH: CS 低
SPI_FLASH_CS_LOW();
//发送 读状态寄存器 命令
SPI_FLASH_SendByte(W25X_READ_STATUS_REG);
SPITimeout = SPIT_FLAG_TIMEOUT;
//若FLASH忙碌,则等待
do
{
//读取FLASH芯片的状态寄存器
flash_Status = SPI_FLASH_SendByte(Dummy_Byte);
if((SPITimeout--) == 0)
{
SPI_TIMEOUT_UserCallback(4);
return;
}
}
while((flash_Status & WIP_Flag) == SET); //正在写入标志
//停止信号 FLASH: CS 高
SPI_FLASH_CS_HIGH();
}
//进入掉电模式
void SPI_Flash_PowerDown(void)
{
//选择 FLASH: CS 低
SPI_FLASH_CS_LOW();
//发送 掉电 命令
SPI_FLASH_SendByte(W25X_POWER_DOWN);
//停止信号 FLASH: CS 高
SPI_FLASH_CS_HIGH();
}
//唤醒
void SPI_Flash_WAKEUP(void)
{
//选择 FLASH: CS 低
SPI_FLASH_CS_LOW();
//发上 上电 命令
SPI_FLASH_SendByte(W25X_RELEASE_POWER_DOWN);
//停止信号 FLASH: CS 高
SPI_FLASH_CS_HIGH(); //等待TRES1
}
/*
* @brief 等待超时回调函数
* @param None.
* @retval None.
*/
static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode)
{
//等待超时后的处理,输出错误信息
FLASH_ERROR("SPI 等待超时! errorCode = %d", errorCode);
return 0;
}
bsp_spi_flash.h
#ifndef __SPI_FLASH_H
#define __SPI_FLASH_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include "spi.h"
#include "usart.h"
/* Private typedef ----------------------------------------------------------- */
//#define sFLASH_ID 0xEF3015 //W25X16
//#define sFLASH_ID 0xEF4015 //W25Q16
#define sFLASH_ID 0xEF4017 //W25Q64
//#define sFLASH_ID 0xEF4018 //W25Q128
//#define SPI_FLASH_PageSize 4096
#define SPI_FLASH_PageSize 256
#define SPI_FLASH_PerWritePageSize 256
/* Private define ------------------------------------------------------------*/
/* 命令定义-开头*******************************/
#define W25X_WRITE_ENABLE 0x06
#define W25X_WRITE_DISABLE 0x04
#define W25X_READ_STATUS_REG 0x05
#define W25X_WRITE_STATUS_REG 0x01
#define W25X_READ_DATA 0x03
#define W25X_FAST_READ_DATA 0x0B
#define W25X_FAST_READ_DUAL 0x3B
#define W25X_FAST_READ_QUAD 0x6B
#define W25X_PAGE_PROGRAM 0x02
#define W25X_BLOCK_ERASE 0xD8
#define W25X_SECTOR_ERASE 0x20
#define W25X_CHIP_ERASE 0xC7
#define W25X_POWER_DOWN 0xB9
#define W25X_RELEASE_POWER_DOWN 0xAB
#define W25X_DEVICE_ID 0xAB
#define W25X_MANUFACTURER_ID 0x90
#define W25X_JEDEC_DEVICE_ID 0x9F
#define WIP_Flag 0x01 //Write In Progress (WIP) flag
#define Dummy_Byte 0xFF
/* 命令定义-结尾*******************************/
//CS(NSS)引脚
#define FLASH_CS_PIN GPIO_PIN_12
#define FLASH_CS_GPIO_PORT GPIOB
//设置为高电平
#define SPI_FLASH_CS_HIGH() HAL_GPIO_WritePin(FLASH_CS_GPIO_PORT, FLASH_CS_PIN, GPIO_PIN_SET);
//输出低电平
#define SPI_FLASH_CS_LOW() HAL_GPIO_WritePin(FLASH_CS_GPIO_PORT, FLASH_CS_PIN, GPIO_PIN_RESET);
/*SPI接口定义-结尾****************************/
/* 等待超时时间 */
#define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000)
#define SPIT_LONG_TIMEOUT ((uint32_t)(10 * SPIT_FLAG_TIMEOUT))
/*信息输出*/
#define FLASH_DEBUG_ON 1
#define FLASH_INFO(fmt,arg...) printf("<<-FLASH-INFO->> "fmt"\n",##arg)
#define FLASH_ERROR(fmt,arg...) printf("<<-FLASH-ERROR->> "fmt"\n",##arg)
#define FLASH_DEBUG(fmt, arg...) do{\
if(FLASH_DEBUG_ON)\
printf("<<-FLASH-DEBUG->> [%d]"fmt"\n", __LINE__, ##arg);\
} while(0)
void SPI_FLASH_Init(void);
void SPI_FLASH_SectorErase(uint32_t SectorAddr);
void SPI_FLASH_BulkErase(void);
void SPI_FLASH_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
uint32_t SPI_FLASH_ReadID(void);
uint32_t SPI_FLASH_ReadDeviceID(void);
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr);
void SPI_Flash_PowerDown(void);
void SPI_Flash_WAKEUP(void);
uint8_t SPI_FLASH_ReadByte(void);
uint8_t SPI_FLASH_SendByte(uint8_t byte);
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord);
void SPI_FLASH_WriteEnable(void);
void SPI_FLASH_WriteDisable(void);
void SPI_FLASH_WaitForWriteEnd(void);
#ifdef __cplusplus
}
#endif
#endif /* __SPI_FLASH_H */
注:如果各操作出现失败的情况,可以调整void SPI_FLASH_WaitForWriteEnd(void)中的SPITimeout,由原来的SPIT_FLAG_TIMEOUT调整为SPIT_LONG_TIMEOUT,即10倍的SPIT_FLAG_TIMEOUT(见bsp_spi_flash.h中相应的宏定义)。