这个例程建立在已经有了SPI驱动的条件下
1 cubemx 配置
勾选user-defiend, 4096 扇区支持
如果要支持中文和长文件名勾选这个
设置堆栈大小
2 代码配置
user_disokio.c中添加读写函数
1 初始化
DSTATUS USER_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
/* USER CODE BEGIN INIT */
Stat = STA_NOINIT;
if(SPI_FLASH_ReadID() == sFLASH_ID){
Stat &= ~STA_NOINIT;
}else{
printf("fatfs flash init begin error\r\n");
}
return Stat;
/* USER CODE END INIT */
}
2 获取状态
DSTATUS USER_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
/* USER CODE BEGIN STATUS */
Stat = STA_NOINIT;
//printf("------- this is fatfs flash get status ok---\r\n");
if(SPI_FLASH_ReadID() == sFLASH_ID){
Stat = ~STA_NOINIT;
//printf("------- this is fatfs flash get status ok---\r\n");
}else{
Stat = STA_NOINIT;
}
return Stat;
/* USER CODE END STATUS */
}
3 读取
因为sector 和count单位不一样, 要进行转换
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 <<12, count<<12);
return RES_OK;
/* USER CODE END READ */
}
4 写入
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 */
uint32_t write_addr;
write_addr = sector<<12;
SPI_FLASH_SectorErase(write_addr);
SPI_FLASH_BufferWrite((uint8_t *)buff,write_addr,count<<12);
return RES_OK;
/* USER CODE END WRITE */
}
5 控制
#define SPI_FLASH_FATFS_SIZE (8*1024*1024) // 用作fatfs的大小
#define SPI_FLASH_BLOCK_SIZE 4096
#define SPI_FLASH_FATFS_SELECTOR_SIZE (SPI_FLASH_FATFS_SIZE/SPI_FLASH_BLOCK_SIZE) // fatfs占用的扇区
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) {
/* 扇区数量:2560*4096/1024/1024=10(MB) */
case GET_SECTOR_COUNT:
*(DWORD * )buff = SPI_FLASH_FATFS_SELECTOR_SIZE;//768-3M//1024;
break;
/* 扇区大小 */
case GET_SECTOR_SIZE :
*(WORD * )buff = SPI_FLASH_BLOCK_SIZE;
break;
/* 同时擦除扇区个数 */
case GET_BLOCK_SIZE :
*(DWORD * )buff = 1;
break;
}
res = RES_OK;
return res;
/* USER CODE END IOCTL */
}
3 测试
FATFS spi_flash;
void fatfs_spi_flash_init()
{
FRESULT retSD;
// 挂载spi flash -- 如果userfs不能用, 就用自己定义的fatfs
retSD = f_mount(&spi_flash, USERPath, 0);
// 如果挂载不成功
if(retSD)
{
// 如果没文件系统
if(retSD == FR_NO_FILESYSTEM)
{
printf("mkfs spi-flash \r\n");
retSD = f_mkfs(USERPath,FM_FAT,0,work_buffer,WORK_BUFFER_SIZE);
if(retSD == FR_OK)
{
retSD = f_mount(&USERFatFS, USERPath, 0);
if(retSD == FR_OK) {
printf("spi-flash init fs ok!\r\n");
}
}
}
else {
printf("spi-flash init fs ok!\r\n");
}
}else {
printf(" mount spi-flash ok\r\n");
}
// uint32_t total,free;
// exf_getfree("1:",&total,&free);
// printf("flash size:%d KB %dMB, free size:%d KB %dMB\r\n",total,total/1024,free,free/1024);
}
static void fatfs_test(char *filename_t)
{
fr = f_open(&fd, filename_t, FA_CREATE_ALWAYS | FA_WRITE);
if(fr == FR_OK)
{
printf("\r\nfatfs open file ok\r\n");
fr = f_write(&fd, write_dat, sizeof(write_dat), (void *)&write_num);
fr = f_close(&fd);
if(fr == FR_OK)
{
retSD = f_open(&fd, filename_t, FA_OPEN_EXISTING | FA_READ);
if(retSD == FR_OK)
{
retSD = f_read(&fd, read_buf, sizeof(read_buf), &count);
if(retSD != FR_OK)
{
f_close(&fd);
}
else
{
printf("\r\nfatfs read buf:%s\r\n", read_buf);
f_close(&fd);
}
}
}
}else{
printf("\r\nfatfs open file error\r\n");
}
}
main.c调用
注意我这里已经有了sd fatfs, 所以spi-flash是1, 如果没有设置sd, 那么flash就是0
fatfs_spi_flash_init();
fatfs_test("1:test.txt");