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

来源:互联网 发布:易观千帆数据哪来的 编辑:程序博客网 时间:2024/06/15 20:34

首先配置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_COUNT200#define BLOCK_SIZE65536#define FLASH_PAGES_PER_SECTORSECTOR_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 == 1DRESULT 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 == 1DRESULT 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);  }}




0 0
原创粉丝点击