使用STM32CUBEMX生成FatFS代码,操作SPI FLASH

首先配置SPI,我的板子是SPI2连接到SPI FLASH 上,我的flash是W25Q64, PB12用来当CSN。

接下来配置FATFS,这里选择用户定义的。

配置FATFS的时候要注意,由于SPI FLASH 的sector是4096字节的,故需要设置sector的大小为4096,其余选项根据自己情况配置。

配置好了生成代码和工程。记得把堆栈尺寸调大一些。我用IAR这样配置:

接着把SPI FLASH的读写操作实现:读一个sector和写一个sector。我写好的函数叫做W25_WriteSector和W25_ReadSector. 然后定义好常量:

#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

下一步打开user_diskio.c 文件,填充几个函数。

/**
  * @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 HERE */
  UINT i = 0;
  for(i = 0; i < count; i ++)
  {
    W25_ReadSector(sector, buff);
    sector ++;
    buff += SECTOR_SIZE;
  }
  return RES_OK;
}

/**
  * @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 HERE */
  UINT i = 0;
  for(i = 0; i < count; i ++)
  {
    W25_WriteSector(sector, buff);
    sector ++;
    buff += SECTOR_SIZE;
  }
  return RES_OK;
}
#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 */
)
{
  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;
}
#endif /* _USE_IOCTL == 1 */

这些函数填充好,就可以用FATFS了。对于一个新的SPI FLASH,先挂载f_mount,再格式化文件系统f_mkfs,之后就可以做各种新建文件、读写操作了。

补充一个,在fatfs.c 文件中,定义了这样一个:

char USER_Path[4];  /* USER logical drive path */

之后我们可以在main或者其他文件里用extern声明它,mount和mkfs时的USER_Path都是它。

附上我的测试代码

void mount_disk(void)
{
  uint8_t res = f_mount(&fs, USER_Path, 0);
  if (res != FR_OK)
  {
    printf("FAILED: %d\n",res);
   return;
 }
  printf("MOUNT OK\n");
}

void format_disk(void)
{
  uint8_t res = 0;
      
  printf("PROCESSING...\n");
  res = f_mkfs(USER_Path, 1, 4096);
  if (res == FR_OK)
  {
    printf("OK!\n");
  }
  else
  {
    printf("failed with: %d\n",res);
  }
}

void create_file(void)
{
  FIL file;
  FIL *pf = &file;
  uint8_t res;
	
  res = f_open(pf, "0:/test.txt", FA_OPEN_ALWAYS | FA_WRITE);
  if (res == FR_OK)
  {
    printf("creat ok\n"); 				
  }
  else
  {
    printf("creat failed\n");
    printf("error code: %d\n",res);	
  }
  
  f_printf(pf, "hello fatfs!\n");
  
  res = f_close(pf);
    if (res != FR_OK)
    {
      printf("close file error\n");
      printf("error code: %d\n",res);				
    }
}

void get_disk_info(void)
{
	FATFS fs;
	FATFS *fls = &fs;
	FRESULT res;
	DWORD fre_clust;	

	res = f_getfree("/",&fre_clust,&fls);         /* Get Number of Free Clusters */
	if (res == FR_OK) 
	{
	                                             /* Print free space in unit of MB (assuming 4096 bytes/sector) */
        printf("%d KB Total Drive Space.\n"
               "%d KB Available Space.\n",
               ((fls->n_fatent-2)*fls->csize)*4,(fre_clust*fls->csize)*4);
	}
	else
	{
		printf("get disk info error\n");
		printf("error code: %d\n",res);
	}																									   
}

void read_file(void)
{
  FIL file;
  FRESULT res;
  UINT bw;
  uint8_t rbuf[100] = {0};
  
  res = f_open(&file, "0:/test.txt", FA_READ);
  if (res != FR_OK)
  {
    printf("open error: %d\n",res);
    return;
  }
  f_read(&file, rbuf, 20, &bw);
  printf("%s\n", rbuf);
  
  res = f_close(&file);
  if (res != FR_OK)
  {
     printf("close file error\n");
     printf("error code: %d\n",res);				
  }
}




猜你喜欢

转载自blog.csdn.net/mengfei314/article/details/50848423