1.系统配置
2.添加硬石 spi Flash驱动
/**
******************************************************************************
* 文件名程: bsp_spiflash.c
* 作 者: 硬石嵌入式开发团队
* 版 本: V1.0
* 编写日期: 2015-10-04
* 功 能: 板载串行Flash底层驱动实现
******************************************************************************
* 说明:
* 本例程配套硬石stm32开发板YS-F1Pro使用。
*
* 淘宝:
* 论坛:http://www.ing10bbs.com
* 版权归硬石嵌入式开发团队所有,请勿商用。
******************************************************************************
*/
/* 包含头文件 ----------------------------------------------------------------*/
#include "bsp_spiflash.h"
/* 私有类型定义 --------------------------------------------------------------*/
/* 私有宏定义 ----------------------------------------------------------------*/
#define SPI_FLASH_PageSize 256
#define SPI_FLASH_PerWritePageSize 256
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg 0x05
#define W25X_WriteStatusReg 0x01
#define W25X_ReadData 0x03
#define W25X_FastReadData 0x0B
#define W25X_FastReadDual 0x3B
#define W25X_PageProgram 0x02
#define W25X_BlockErase 0xD8
#define W25X_SectorErase 0x20
#define W25X_ChipErase 0xC7
#define W25X_PowerDown 0xB9
#define W25X_ReleasePowerDown 0xAB
#define W25X_DeviceID 0xAB
#define W25X_ManufactDeviceID 0x90
#define W25X_JedecDeviceID 0x9F
#define WIP_Flag 0x01 /* Write In Progress (WIP) flag */
#define Dummy_Byte 0xFF
void MX_SPIFlash_Init()
{
uint8_t cmd[2] = {0x66,0x99}; //复位
FLASH_SPI_CS_ENABLE();
HAL_SPI_Transmit(&hspi1,cmd,2,1000);
FLASH_SPI_CS_DISABLE();
}
/**
* 函数功能: 擦除扇区
* 输入参数: SectorAddr:待擦除扇区地址,要求为4096倍数
* 返 回 值: 无
* 说 明:串行Flash最小擦除块大小为4KB(4096字节),即一个扇区大小,要求输入参数
* 为4096倍数。在往串行Flash芯片写入数据之前要求先擦除空间。
*/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
/* 发送FLASH写使能命令 */
SPI_FLASH_WriteEnable();
SPI_FLASH_WaitForWriteEnd();
/* 擦除扇区 */
/* 选择串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
/* 发送扇区擦除指令*/
SPI_FLASH_SendByte(W25X_SectorErase);
/*发送擦除扇区地址的高位*/
SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
/* 发送擦除扇区地址的中位 */
SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
/* 发送擦除扇区地址的低位 */
SPI_FLASH_SendByte(SectorAddr & 0xFF);
/* 禁用串行FLASH: CS 高电平 */
FLASH_SPI_CS_DISABLE();
/* 等待擦除完毕*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* 函数功能: 擦除整片
* 输入参数: 无
* 返 回 值: 无
* 说 明:擦除串行Flash整片空间
*/
void SPI_FLASH_BulkErase(void)
{
/* 发送FLASH写使能命令 */
SPI_FLASH_WriteEnable();
/* 整片擦除 Erase */
/* 选择串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
/* 发送整片擦除指令*/
SPI_FLASH_SendByte(W25X_ChipErase);
/* 禁用串行FLASH: CS高电平 */
FLASH_SPI_CS_DISABLE();
/* 等待擦除完毕*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* 函数功能: 往串行FLASH按页写入数据,调用本函数写入数据前需要先擦除扇区
* 输入参数: pBuffer:待写入数据的指针
* WriteAddr:写入地址
* NumByteToWrite:写入数据长度,必须小于等于SPI_FLASH_PerWritePageSize
* 返 回 值: 无
* 说 明:串行Flash每页大小为256个字节
*/
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
/* 发送FLASH写使能命令 */
SPI_FLASH_WriteEnable();
/* 寻找串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
/* 写送写指令*/
SPI_FLASH_SendByte(W25X_PageProgram);
/*发送写地址的高位*/
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;
//printf("Err: SPI_FLASH_PageWrite too large!\n");
}
/* 写入数据*/
while (NumByteToWrite--)
{
/* 发送当前要写入的字节数据 */
SPI_FLASH_SendByte(*pBuffer);
/* 指向下一字节数据 */
pBuffer++;
}
/* 禁用串行FLASH: CS 高电平 */
FLASH_SPI_CS_DISABLE();
/* 等待写入完毕*/
SPI_FLASH_WaitForWriteEnd();
}
/**
* 函数功能: 往串行FLASH写入数据,调用本函数写入数据前需要先擦除扇区
* 输入参数: pBuffer:待写入数据的指针
* WriteAddr:写入地址
* NumByteToWrite:写入数据长度
* 返 回 值: 无
* 说 明:该函数可以设置任意写入数据长度
*/
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;
Addr = WriteAddr % SPI_FLASH_PageSize;
count = SPI_FLASH_PageSize - Addr;
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
if (Addr == 0) /* 若地址与 SPI_FLASH_PageSize 对齐 */
{
if (NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
{
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);
}
}
else /* 若地址与 SPI_FLASH_PageSize 不对齐 */
{
if (NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
{
if (NumOfSingle > count) /* (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
{
temp = NumOfSingle - count;
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;
SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
}
else
{
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
}
else /* NumByteToWrite > SPI_FLASH_PageSize */
{
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);
}
}
}
}
/**
* 函数功能: 从串行Flash读取数据
* 输入参数: pBuffer:存放读取到数据的指针
* ReadAddr:读取数据目标地址
* NumByteToRead:读取数据长度
* 返 回 值: 无
* 说 明:该函数可以设置任意读取数据长度
*/
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
uint8_t cmd[4];
cmd[0] = W25X_ReadData;
cmd[1] = (ReadAddr & 0xFF0000) >> 16;
cmd[2] = (ReadAddr & 0xFF00) >> 8;
cmd[3] = ReadAddr & 0xFF;
/* 选择串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
HAL_SPI_Transmit(&hspi1,cmd,4,1000);
HAL_SPI_Receive(&hspi1,pBuffer,NumByteToRead,1000);
/* 禁用串行FLASH: CS 高电平 */
FLASH_SPI_CS_DISABLE();
}
/**
* 函数功能: 读取串行Flash型号的ID
* 输入参数: 无
* 返 回 值: uint32_t:串行Flash的型号ID
* 说 明: FLASH_ID IC型号 存储空间大小
0xEF3015 W25X16 2M byte
0xEF4015 W25Q16 4M byte
0XEF4017 W25Q64 8M byte
0XEF4018 W25Q128 16M byte (YS-F1Pro开发板默认配置)
*/
uint32_t SPI_FLASH_ReadID(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/* 选择串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
/* 发送命令:读取芯片型号ID */
SPI_FLASH_SendByte(W25X_JedecDeviceID);
/* 从串行Flash读取一个字节数据 */
Temp0 = SPI_FLASH_SendByte(Dummy_Byte);
/* 从串行Flash读取一个字节数据 */
Temp1 = SPI_FLASH_SendByte(Dummy_Byte);
/* 从串行Flash读取一个字节数据 */
Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
/* 禁用串行Flash:CS高电平 */
FLASH_SPI_CS_DISABLE();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}
/**
* 函数功能: 读取串行Flash设备ID
* 输入参数: 无
* 返 回 值: uint32_t:串行Flash的设备ID
* 说 明:
*/
uint32_t SPI_FLASH_ReadDeviceID(void)
{
uint32_t Temp = 0;
/* 选择串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
/* 发送命令:读取芯片设备ID * */
SPI_FLASH_SendByte(W25X_DeviceID);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
SPI_FLASH_SendByte(Dummy_Byte);
/* 从串行Flash读取一个字节数据 */
Temp = SPI_FLASH_SendByte(Dummy_Byte);
/* 禁用串行Flash:CS高电平 */
FLASH_SPI_CS_DISABLE();
return Temp;
}
/**
* 函数功能: 启动连续读取数据串
* 输入参数: ReadAddr:读取地址
* 返 回 值: 无
* 说 明: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.
*/
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr)
{
/* Select the FLASH: Chip Select low */
FLASH_SPI_CS_ENABLE();
/* Send "Read from Memory " instruction */
SPI_FLASH_SendByte(W25X_ReadData);
/* 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);
}
/**
* 函数功能: 从串行Flash读取一个字节数据
* 输入参数: 无
* 返 回 值: uint8_t:读取到的数据
* 说 明:This function must be used only if the Start_Read_Sequence
* function has been previously called.
*/
uint8_t SPI_FLASH_ReadByte(void)
{
uint8_t d_read,d_send=Dummy_Byte;
if(HAL_SPI_TransmitReceive(&hspi1,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
d_read=Dummy_Byte;
return d_read;
}
/**
* 函数功能: 往串行Flash读取写入一个字节数据并接收一个字节数据
* 输入参数: byte:待发送数据
* 返 回 值: uint8_t:接收到的数据
* 说 明:无
*/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
uint8_t d_read,d_send=byte;
if(HAL_SPI_TransmitReceive(&hspi1,&d_send,&d_read,1,0xFFFFFF)!=HAL_OK)
d_read=Dummy_Byte;
return d_read;
}
/**
* 函数功能: 往串行Flash读取写入半字(16bit)数据并接收半字数据
* 输入参数: byte:待发送数据
* 返 回 值: uint16_t:接收到的数据
* 说 明:无
*/
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord)
{
uint8_t d_read[2],d_send[2];
d_send[0]=HalfWord&0x00FF;
d_send[1]=(HalfWord>>8)&0x00FF;
if(HAL_SPI_TransmitReceive(&hspi1,d_send,d_read,2,0xFFFFFF)!=HAL_OK)
{
d_read[0]=Dummy_Byte;
d_read[1]=Dummy_Byte;
}
return ((d_read[1]<<8)+d_read[0]);
}
/**
* 函数功能: 使能串行Flash写操作
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void SPI_FLASH_WriteEnable(void)
{
/* 选择串行FLASH: CS低电平 */
FLASH_SPI_CS_ENABLE();
/* 发送命令:写使能 */
SPI_FLASH_SendByte(W25X_WriteEnable);
/* 禁用串行Flash:CS高电平 */
FLASH_SPI_CS_DISABLE();
}
/**
* 函数功能: 等待数据写入完成
* 输入参数: 无
* 返 回 值: 无
* 说 明:Polls the status of the Write In Progress (WIP) flag in the
* FLASH's status register and loop until write opertaion
* has completed.
*/
void SPI_FLASH_WaitForWriteEnd(void)
{
uint8_t FLASH_Status = 0;
/* Select the FLASH: Chip Select low */
FLASH_SPI_CS_ENABLE();
/* Send "Read Status Register" instruction */
SPI_FLASH_SendByte(W25X_ReadStatusReg);
/* Loop as long as the memory is busy with a write cycle */
do
{
/* Send a dummy byte to generate the clock needed by the FLASH
and put the value of the status register in FLASH_Status variable */
FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);
}
while ((FLASH_Status & WIP_Flag) == SET); /* Write in progress */
/* Deselect the FLASH: Chip Select high */
FLASH_SPI_CS_DISABLE();
}
/**
* 函数功能: 进入掉电模式
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void SPI_Flash_PowerDown(void)
{
/* Select the FLASH: Chip Select low */
FLASH_SPI_CS_ENABLE();
/* Send "Power Down" instruction */
SPI_FLASH_SendByte(W25X_PowerDown);
/* Deselect the FLASH: Chip Select high */
FLASH_SPI_CS_DISABLE();
}
/**
* 函数功能: 唤醒串行Flash
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
void SPI_Flash_WAKEUP(void)
{
/* Select the FLASH: Chip Select low */
FLASH_SPI_CS_ENABLE();
/* Send "Power Down" instruction */
SPI_FLASH_SendByte(W25X_ReleasePowerDown);
/* Deselect the FLASH: Chip Select high */
FLASH_SPI_CS_DISABLE();
}
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
3.flash.h
#ifndef __BSP_SPIFLASH_H__
#define __BSP_SPIFLASH_H__
/* 包含头文件 ----------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "spi.h"
/* 类型定义 ------------------------------------------------------------------*/
/* 宏定义 --------------------------------------------------------------------*/
//W25Q
//#define SPI_FLASH_ID 0xEF3015 //W25X16 2MB
//#define SPI_FLASH_ID 0xEF4015 //W25Q16 4MB
//#define SPI_FLASH_ID 0XEF4017 //W25Q64 8MB
//#define SPI_FLASH_ID 0XEF4018 //W25Q128 16MB YS-F1Pro开发默认使用
//XT25F
//#define SPI_FLASH_ID 0x0B3015 //XT25F16 2MB
//#define SPI_FLASH_ID 0x0B4015 //XT25F16 4MB
//#define SPI_FLASH_ID 0X0B4017 //XT25F64 8MB
#define SPI_FLASH_ID 0X0B4018 //XT25F128 16MB
#define Flash_OK 0x00
#define Flash_Error 0x01
#define Flash_Busy 0x02
#define Flash_Timeout 0x03
#define Flash_Block_Size 1 //块大小
#define Flash_Sector_Count 4096 //XT25F128 16M 有256块 1块有16个扇区 256*16=4096个扇区 扇区总数量
#define Flash_Sector_Size 4096 //1个扇区有16页 1页有256个字节 16*256=4096 扇区大小
#define FLASH_SPI_CS_ENABLE() HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET)
#define FLASH_SPI_CS_DISABLE() HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET)
/* 函数声明 ------------------------------------------------------------------*/
void MX_SPIFlash_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_WaitForWriteEnd(void);
uint8_t Flash_Read(uint8_t *pData, uint32_t ReadAddr, uint32_t Size);
#endif /* __BSP_SPIFLASH_H__ */
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/
4. USB驱动Flash定义
#include "bsp_spiflash.h" //添加Flash头文件
int8_t STORAGE_Init_FS(uint8_t lun) //初始化
{
/* USER CODE BEGIN 2 */
MX_SPIFlash_Init();
return (USBD_OK);
/* USER CODE END 2 */
}
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)//获取内存信息
{
/* USER CODE BEGIN 3 */
*block_num = Flash_Sector_Count; //获取扇区数量
*block_size = Flash_Sector_Size; //获取扇区大小
return (USBD_OK);
/* USER CODE END 3 */
}
//以扇区读取
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
SPI_FLASH_BufferRead(buf, blk_addr*Flash_Sector_Size, blk_len*Flash_Sector_Size);
return (USBD_OK);
/* USER CODE END 6 */
}
//写扇区数据,先擦除
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
SPI_FLASH_SectorErase(blk_addr*Flash_Sector_Size);
SPI_FLASH_BufferWrite(buf, blk_addr*Flash_Sector_Size, blk_len*Flash_Sector_Size);
return (USBD_OK);
/* USER CODE END 7 */
}
5.Fatfs定义
#include "bsp_spiflash.h" //添加Flash头文件
//初始化
DSTATUS USER_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
/* USER CODE BEGIN INIT */
MX_SPIFlash_Init();
if(SPI_FLASH_ReadID() != SPI_FLASH_ID)
Stat = RES_ERROR;
else Stat = RES_OK;
return Stat;
/* USER CODE END INIT */
}
//状态获取
DSTATUS USER_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
/* USER CODE BEGIN STATUS */
Stat = RES_OK;
return Stat;
/* USER CODE END STATUS */
}
//读取数据 以扇区读取
DRESULT USER_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
/* USER CODE BEGIN READ */
SPI_FLASH_BufferRead(buff, sector*Flash_Sector_Size, count*Flash_Sector_Size);
return RES_OK;
/* USER CODE END READ */
}
//写数据
DRESULT USER_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
/* USER CODE BEGIN WRITE */
/* USER CODE HERE */
SPI_FLASH_SectorErase(sector*Flash_Sector_Size);
SPI_FLASH_BufferWrite((BYTE*)buff, sector*Flash_Sector_Size, count*Flash_Sector_Size);
return RES_OK;
/* USER CODE END WRITE */
}
//获取Flash信息
DRESULT USER_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
/* USER CODE BEGIN IOCTL */
DRESULT res = RES_ERROR;
switch(cmd)
{
case GET_BLOCK_SIZE: *(WORD*)buff = Flash_Block_Size ; res = RES_OK ;break; //获取块
case GET_SECTOR_SIZE: *(WORD*)buff = Flash_Sector_Size ; res = RES_OK ;break; //获取Flash扇区大小
case GET_SECTOR_COUNT: *(WORD*)buff = Flash_Sector_Count ; res = RES_OK ;break; //获取Flash扇区数量
default:res = RES_PARERR ; break;
}
return res;
/* USER CODE END IOCTL */
}
6.主函数
#include "stdio.h"
#include "ff.h"
#include "diskio.h"
#include "bsp_spiflash.h"
FATFS user_fat; //fatfs文件系统对象
FIL file; //文件对象
FRESULT res; //文件操作结果
UINT ff_num; //文件成功读取数量
DIR dir; //文件夹名称
FILINFO info; //文件信息读取保存
BYTE buff[90]={0}; //文件缓存区
uint8_t TestBuffer[33]={"文件系统测试数据 FATFS TEST DATA"};
//printf重定义
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFF);
return ch;
}
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t size=0;
/* 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_SPI1_Init();
MX_USART1_UART_Init();
MX_FATFS_Init();
MX_USB_DEVICE_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(1000); //等待系统稳定,必要延时
if(SPI_FLASH_ReadID() != SPI_FLASH_ID) printf("Flash init Fail\r\n");
else printf("Flash init OK\r\n");
res = f_mount(&user_fat,"",0); //挂载flash
printf("f_mount Fail :%d\r\n",res);
if(res == FR_NO_FILESYSTEM)
{
res = f_mkfs("", 0, 0); //格式化
if(res != RES_OK)
printf("f_mkfs Fail:%d\r\n",res);
else
printf("f_mkfs OK\r\n");
}
res = f_open(&file,"bb.txt",FA_CREATE_ALWAYS | FA_WRITE | FA_READ); //打开一个文件,有则打开,无则新建
printf("f_open: %d\r\n",res);
res = f_write(&file,TestBuffer,32,&ff_num);
printf("f_write: %d\r\n",res);
f_close(&file);
memset(TestBuffer,0,32); //清零
f_open(&file,"bb.txt",FA_READ); //读取文件
res = f_read(&file,TestBuffer,32,&ff_num); //保存数据
printf("f_read: %d\r\n",res);
f_close(&file);
// TestBuffer[32] = '\0'; //添加结束符,不然打印末尾会乱码
size = f_size(&file); //获取文件长度
printf("size:%d ",size);
printf("DATA:%s",TestBuffer);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
7.调试