当前位置:   article > 正文

基于STM32CubeMX的片外SPIFLASH嵌入FATFS_spi flash fatfs

spi flash fatfs

最近有一个关于SPIFLASH嵌入FATFS的需求,自己也是第一次搞,在此做一个实验记录,方便后期查看。
注:本博客借鉴了Carry_王的博客,修正了一下小错误之后,能够直接实现FATFS的移植和使用,大部分代码是参照上面码哥的,大家也可以自行对比一下。

顺便一提,所有动作的本质还是MCU通过SPI总线与Flash通信,只是借助了FATFS协议栈对Flash进行管理,FATFS由纯软件构成。

整体结构

这里我使用的平台是硬石的YS-F4Pro运动控制板,MCU是STM32F407IGTb,片外Flash使用的是16M的W25Q128,具体思路如下:

  1. 利用HAL库实现标准的MCU利用SPI与Flash通信进行读写;
  2. 此时基本功能【此时ID读取即可】
  3. 在STM32CubeMX使能FATFS;
  4. 在FATFS的用户接口中写入访问片外Flash的读写以及控制等函数;
  5. 此时FATFS是否能正常使用【测试标准FATFS读写】。

操作步骤

  1. 打开STM32CubeMX,选择芯片:在这里插入图片描述

  2. 配置系统Debug方式以及时钟来源在这里插入图片描述

  3. 配置外部时钟在这里插入图片描述

  4. 配置SPI(这里要根据硬件电路对应的SPI来进行匹配,片选PI0,输出PC2,输入PI3,时钟PI1)
    在这里插入图片描述
    在这里插入图片描述

  5. 配置片选信号PI0,该处不具体将SPI的通信,如有不解需参考SPI的通信说明在这里插入图片描述

  6. 为了后面不麻烦,这里把文件系统也配置进去,因为使用的是W25Q128,每个扇区大小为4096,所以此处将最大最小扇区定义为4096在这里插入图片描述

  7. 时钟树配置,主频为72M在这里插入图片描述

  8. 完成代码配置(选择必要的文件这项点上之后不会添加额外库文件,能减少无谓的编译时间)在这里插入图片描述

  9. 内嵌Flash芯片的驱动文件(这里直接贴我修改后的源码)
    代码的具体意思我就不分析了,注释大部分都有
    SPIFLASH.c

#ifndef __SPIFLASH_H__
#define __SPIFLASH_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "main.h"
#include "SPIFLASH.h"
#include "spi.h"

#define W25Q80 	0XEF13 	
#define W25Q16 	0XEF14
#define W25Q32 	0XEF15
#define W25Q64 	0XEF16
#define W25Q128	0XEF17
#define  M25P64_FLASH_ID        0x202017//C22017
#define  M25P40_FLASH_ID        0x202013

/* USER CODE BEGIN Includes */
#define sFLASH_CMD_WRITE          0x02  /*!< Write to Memory instruction */
#define sFLASH_CMD_WRSR           0x01  /*!< Write Status Register instruction */
#define sFLASH_CMD_WREN           0x06  /*!< Write enable instruction */
#define sFLASH_CMD_READ           0x03  /*!< Read from Memory instruction */
#define sFLASH_CMD_RDSR           0x05  /*!< Read Status Register instruction  */
#define sFLASH_CMD_RDID           0x9F  /*!< Read identification */
#define sFLASH_CMD_SE             0x20  /*!< Sector Erase instruction (4k)*/
#define sFLASH_CMD_BE             0xD8  /*!< Block Erase instruction (64k)*/
#define sFLASH_CMD_CE             0xC7  /*!< Chip Erase instruction (Chip Erase)*/
#define sFLASH_WIP_FLAG           0x01  /*!< Write In Progress (WIP) flag */
#define sFLASH_CMD_RDID           0x9F  /*!< Read identification */
#define sFLASH_CMD_DeviceID			    0xAB 
#define sFLASH_CMD_ManufactDeviceID	    0x90 
#define sFLASH_CMD_JedecDeviceID		0x9F 
#define sFLASH_DUMMY_BYTE         0xFF

uint8_t sFlashBuff[4096];

//片选CS拉低
void sFLASH_CS_LOW(void)
{
    HAL_GPIO_WritePin(SPIFLASH_CS_GPIO_Port,SPIFLASH_CS_Pin,GPIO_PIN_RESET);
}	
//片选CS拉高
void sFLASH_CS_HIGH(void)
{
    HAL_GPIO_WritePin(SPIFLASH_CS_GPIO_Port,SPIFLASH_CS_Pin,GPIO_PIN_SET);
}	

//FLASH 发送一个字节
char sFLASH_SendByte(uint8_t byte)
{
//	unsigned char dr;
//  /*!< Loop while DR register in not emplty */
//  //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
//	while((SPI2->SR & SPI_SR_TXE) == 0);

//  /*!< Send byte through the SPI1 peripheral */
//  //SPI_I2S_SendData(SPI1, byte);
//	SPI2->DR = byte;

//  /*!< Wait to receive a byte */
//  //while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
//	while((SPI2->SR & SPI_SR_RXNE) == 0);

//  /*!< Return the byte read from the SPI bus */
//  //return SPI_I2S_ReceiveData(SPI1);
//	dr = SPI2->DR;
//	return dr;
	uint8_t d_read,d_send = byte;
	if(HAL_SPI_TransmitReceive(&hspi2,&d_send,&d_read,1,0xFFFF) != HAL_OK)
	{
		d_read = sFLASH_DUMMY_BYTE;
	}
	return d_read;
}

//FLASH写使能
void sFLASH_WriteEnable(void)
{
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send "Write Enable" instruction */
  sFLASH_SendByte(sFLASH_CMD_WREN);

  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();
}

//FLASH读取一个字节
uint8_t sFLASH_ReadByte(void)
{
  return (sFLASH_SendByte(sFLASH_DUMMY_BYTE));
}
//FLASH等待写完成
void sFLASH_WaitForWriteEnd(void)
{
    uint8_t flashstatus = 0;
    HAL_Delay(1);
    /*!< Select the FLASH: Chip Select low */
    sFLASH_CS_LOW();
    HAL_Delay(1);
    /*!< Send "Read Status Register" instruction */
    sFLASH_SendByte(sFLASH_CMD_RDSR);

    /*!< 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 */
    flashstatus = sFLASH_SendByte(sFLASH_DUMMY_BYTE);

    }
    while ((flashstatus & sFLASH_WIP_FLAG) == SET); /* Write in progress */

    /*!< Deselect the FLASH: Chip Select high */
    sFLASH_CS_HIGH();
}

//FLASH擦除一个扇区
void sFLASH_EraseSector(uint32_t SectorAddr)
{
  /*!< Send write enable instruction */
	sFLASH_WriteEnable();
  /*!< Sector Erase */
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send Sector Erase instruction */
	sFLASH_SendByte(sFLASH_CMD_SE);
  /*!< Send SectorAddr high nibble address byte */
  sFLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
  /*!< Send SectorAddr medium nibble address byte */
  sFLASH_SendByte((SectorAddr & 0xFF00) >> 8);
  /*!< Send SectorAddr low nibble address byte */
  sFLASH_SendByte(SectorAddr & 0xFF);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();

  /*!< Wait the end of Flash writing */
  sFLASH_WaitForWriteEnd();
}
//FLASH擦除整个片
void sFLASH_EraseChip(void)
{
  /*!< Send write enable instruction */
  sFLASH_WriteEnable();

  /*!< Bulk Erase */
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send Bulk Erase instruction  */
  sFLASH_SendByte(sFLASH_CMD_CE);
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();

  /*!< Wait the end of Flash writing */
  sFLASH_WaitForWriteEnd();
}
//FLASH写一个页
void sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
    sFLASH_WriteEnable();
    sFLASH_CS_LOW();
    sFLASH_SendByte(sFLASH_CMD_WRITE);
    sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
    sFLASH_SendByte((WriteAddr & 0xFF00) >> 8);
    sFLASH_SendByte(WriteAddr & 0xFF);

    while (NumByteToWrite--)
    {
        sFLASH_SendByte(*pBuffer);
        pBuffer++;
    }

    sFLASH_CS_HIGH();
    sFLASH_WaitForWriteEnd();
}
//FLASH读取0-65536个
void sFLASH_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
    sFLASH_CS_LOW();
    sFLASH_SendByte(sFLASH_CMD_READ);
    sFLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
    sFLASH_SendByte((ReadAddr& 0xFF00) >> 8);
    sFLASH_SendByte(ReadAddr & 0xFF);

    while (NumByteToRead--) /*!< while there is data to be read */
    {
        *pBuffer = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
        pBuffer++;
    }

    sFLASH_CS_HIGH();
}
//读取FLASH ID
uint32_t sFLASH_ReadID(void)
{
    uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
    sFLASH_CS_LOW();
    HAL_Delay(1);
    sFLASH_SendByte(sFLASH_CMD_RDID);
    Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
    Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
    Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);

    sFLASH_CS_HIGH();
    Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

    return Temp;
}
//无检验写SPI FLASH 
void sFLASH_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
{ 			 		 
	uint16_t pageremain;	   
	pageremain=256-WriteAddr%256; //单页剩余的字节数		 	    
	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
	while(1)
	{	   
		sFLASH_WritePage(pBuffer,WriteAddr,pageremain);
		if(NumByteToWrite==pageremain)
        {
            break;//写入结束了
        }
	 	else //NumByteToWrite>pageremain
		{
			pBuffer+=pageremain;
			WriteAddr+=pageremain;	

			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
			if(NumByteToWrite>256)
            {
                pageremain=256; //一次可以写入256个字节
            }
			else
            {
                pageremain=NumByteToWrite; 	  //不够256个字节了
            }
		}
	}
}
//带擦除的写0-65536个字节函数
void sFLASH_WriteBuffer(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
{ 
	uint32_t secpos;
	uint16_t secoff;
	uint16_t secremain;	   
 	uint16_t i;    
	uint8_t * psFlashBuff;	  
  psFlashBuff=sFlashBuff;	     
 	secpos=WriteAddr/4096;//扇区地址  
	secoff=WriteAddr%4096;//在扇区内的偏移
	secremain=4096-secoff;//扇区剩余空间大小   
 	if(NumByteToWrite<=secremain)
    {
        secremain=NumByteToWrite;//不大于4096个字节
    }
    
	while(1) 
	{	
		sFLASH_ReadBuffer(psFlashBuff,secpos*4096,4096);//读出整个扇区的内容      
		sFLASH_EraseSector(secpos*4096);		//擦除这个扇区
		for(i=0;i<secremain;i++)	   		//复制
		{
			psFlashBuff[i+secoff]=pBuffer[i];	  
		}
		sFLASH_Write_NoCheck(psFlashBuff,secpos*4096,4096);//写入整个扇区  
        
		if(NumByteToWrite==secremain)
        {
            break;//写入结束了
        }
		else//写入未结束
		{
      secpos++;//扇区地址增1
      secoff=0;//偏移位置为0 	 

      pBuffer+=secremain;  				//指针偏移
      WriteAddr+=secremain;				//写地址偏移	   
      NumByteToWrite-=secremain;			//字节数递减
      if(NumByteToWrite>4096)
      {
        secremain=4096;//下一个扇区还是写不完
      }
      else 
      {
        secremain=NumByteToWrite;		//下一个扇区可以写完了
      }
		}	 
	}
}

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293

SPIFLASH.h

#ifndef __SPIFLASH_H__
#define __SPIFLASH_H__

/**Includes************************************************************************************/
#include "stm32f4xx_hal.h"
#include "spi.h"

/**Function declaration************************************************************************/


void sFLASH_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
void sFLASH_EraseChip(void);
void sFLASH_WritePage(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void sFLASH_ReadBuffer(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
uint32_t sFLASH_ReadID(void);
char sFLASH_SendByte(uint8_t byte);

void FileTest(void);//该句代码为测试代码,函数在user_diskio.c中定义
#endif


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  1. 在main.c函数调用如下函数检查是否读取出Flash的ID值,读取成功则说明SPI设置没问题
uint32_t Flash_ID = 0;

Flash_ID = sFLASH_ReadID();

  • 1
  • 2
  • 3
  • 4
  1. 在文件系统接口函数user_diskio.c中,修改为如下内容,我直接贴文件全部内容,以防因未粘贴部分设置问题导致的无法使用:
    user_diskio.c
/* USER CODE BEGIN Header */
/**
 ******************************************************************************
  * @file    user_diskio.c
  * @brief   This file includes a diskio driver skeleton to be completed by the user.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */
 /* USER CODE END Header */

#ifdef USE_OBSOLETE_USER_CODE_SECTION_0
/*
 * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
 * To be suppressed in the future.
 * Kept to ensure backward compatibility with previous CubeMx versions when
 * migrating projects.
 * User code previously added there should be copied in the new user sections before
 * the section contents can be deleted.
 */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#endif

/* USER CODE BEGIN DECL */

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "ff_gen_drv.h"

#include "spi.h"
#include "SPIFLASH.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;

#define PAGE_SIZE       256
#define SECTOR_SIZE     4096
#define SECTOR_COUNT	200
#define BLOCK_SIZE	65536
#define FLASH_PAGES_PER_SECTOR	SECTOR_SIZE/PAGE_SIZE

FATFS fs;
FIL file;						  /* 文件对象 */
FRESULT f_res;                    /* 文件操作结果 */
UINT fnum;            					  /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0};        /* 读缓冲区 */
BYTE WriteBuffer[]= "WWB is the high hand\n";
BYTE work[4096];
 
char USER_Path[4];

void mount_disk(void)
{
   f_res = f_mount(&fs, USER_Path, 0);
   return;

}

void format_disk(void)
{
  uint8_t res = 0;
  //这里根据版本不同函数输入参数不一样
  f_res = f_mkfs(USER_Path, 1, 4096, work, sizeof(work));
}

 UINT bw;
void create_file(void)
{
  FIL file;
  FIL *pf = &file;
  uint8_t res;
  f_res = f_open(pf, "0:/test.txt", FA_OPEN_ALWAYS | FA_WRITE);
  f_res = f_write(&file, WriteBuffer, sizeof(WriteBuffer), &bw);
  f_res = f_close(pf);
}

void read_file(void)
{
  FIL file;
  FRESULT res;
  uint8_t rbuf[100] = {0};
  f_res = f_open(&file, "0:/test.txt", FA_READ);
  f_res = f_read(&file, ReadBuffer, sizeof(WriteBuffer), &bw);
  f_res = f_close(&file);
}

void FileTest(void)
{
	mount_disk();		//文件系统注册
	format_disk();		//格式化文件系统
	create_file();		//建立文件并写入"WWB is the high hand\n"
	read_file();		//读取文件放到ReadBuffer中
}
/* USER CODE END DECL */

/* Private function prototypes -----------------------------------------------*/
DSTATUS USER_initialize (BYTE pdrv);
DSTATUS USER_status (BYTE pdrv);
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
//#if _USE_WRITE == 1
  DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
//#endif /* _USE_WRITE == 1 */
//#if _USE_IOCTL == 1
  DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
//#endif /* _USE_IOCTL == 1 */

Diskio_drvTypeDef  USER_Driver =
{
  USER_initialize,
  USER_status,
  USER_read,
#if  _USE_WRITE == 1
  USER_write,
#endif  /* _USE_WRITE == 1 */
#if  _USE_IOCTL == 1
  USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Initializes a Drive
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_initialize (
	BYTE pdrv           /* Physical drive nmuber to identify the drive */
)
{
  /* USER CODE BEGIN INIT */
    Stat = STA_NOINIT;
	if(sFLASH_ReadID() != 0)
		{
			Stat &= ~STA_NOINIT;
		}	
    return Stat;
  /* USER CODE END INIT */
}

/**
  * @brief  Gets Disk Status
  * @param  pdrv: Physical drive number (0..)
  * @retval DSTATUS: Operation status
  */
DSTATUS USER_status (
	BYTE pdrv       /* Physical drive number to identify the drive */
)
{
  /* USER CODE BEGIN STATUS */
    Stat &= ~STA_NOINIT;
    return Stat;
  /* USER CODE END STATUS */
}

/**
  * @brief  Reads Sector(s)
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
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 */
	DRESULT res = RES_ERROR;
	UINT i;
  
	for(i = 0;i < count;i++)
	{
		sFLASH_ReadBuffer(buff + i * 4096,sector * 4096 + i * 4096,4096 );
	}
   
	return RES_OK;
  /* USER CODE END READ */
}

/**
  * @brief  Writes Sector(s)
  * @param  pdrv: Physical drive number (0..)
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
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 */
	DRESULT res = RES_ERROR;
	
	UINT i;
  
	for(i = 0;i < count;i++)
	{
		sFLASH_WriteBuffer((void *)(buff + i * 4096),sector * 4096 + i * 4096,4096 );
	}
	
	res = RES_OK;
  /* USER CODE HERE */
    return res;
  /* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */

/**
  * @brief  I/O control operation
  * @param  pdrv: Physical drive number (0..)
  * @param  cmd: Control code
  * @param  *buff: Buffer to send/receive control data
  * @retval DRESULT: Operation result
  */
#if _USE_IOCTL == 1
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_OK;
	switch(cmd)
	{
		case CTRL_SYNC :
			break;	
	 
		case CTRL_TRIM:
			break;
			
		case GET_BLOCK_SIZE:
		*(DWORD*)buff = BLOCK_SIZE; 
		break;
			
		case GET_SECTOR_SIZE:
		*(DWORD*)buff = SECTOR_SIZE;
			break;
			
		case GET_SECTOR_COUNT:
		*(DWORD*)buff = SECTOR_COUNT;
		break;
				
		default:
		res = RES_PARERR;
		break;
	  }
    return res;
  /* USER CODE END IOCTL */
}
#endif /* _USE_IOCTL == 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  1. 在main.c中调用FileTest();函数
    在这里插入图片描述

测试

编译下载后进入Debug模式,监视ReadBuffer数组【数据为空】和WriteBuffer数组配【数据为需要写入的数据】
在这里插入图片描述
在这里插入图片描述
点击左上角运行代码,查看ReadBuffer数组是否读取到WriteBuffer中的写入值

在这里插入图片描述
点击之后,稍微等待2秒左右【期间要初始化各种外设以及文件系统,再与Flash通信】得到如下结果,ReadBuffer内读取到了之前写入的内容
在这里插入图片描述

到此为止,打完收工,顺便祝大家端午假快乐

Good Game!!!!!!
ASWaterbenben专注于STM32CubeMX的使用研究
有需要的猿们敬请关注!!!!!
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/464045
推荐阅读
相关标签
  

闽ICP备14008679号