HAL-STM32-USB-FLASH-FATFS系统文件

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.调试

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值