概述
FATFS文件系统可以挂载SD卡也可以挂载FLASHeMMC等设备
SD卡需要格式化为
FAT32模式 块大小默认即可

移植
SD卡
SD卡扇区大小是 512B
SD卡 SDIO模式 可以直接在
cubeMX里一键设置
先设置好SD卡的设置
这个是选择支持中文 其余是默认

这个是检测引脚可以留空
当SD卡插入拔出时会引起检测脚的变化

FLASH
FLASH接入FATFS需要自行修改接口,选用自定义模式
建议配合USB MSC功能使用
cubeMX配置
使用自定义模式,将扇区大小改为从512到4096都可

设置内容
全在cubeMX生成的
user_diskio.c中
先导入头文件和设置扇区大小

需要设置的APIs
全在
cubeMX生成的user_diskio.c中
初始化
| 描述 | 名称 | 功能 | 
|---|---|---|
| BYTE(uint8_t) | pdrv | 磁盘编号 | 
| DSTATUS | 输出 | 错误码 | 
DSTATUS USER_initialize (BYTE pdrv)
成功返回
RES_OK失败返回RES_ERROR根据自己初始化写入函数
例子
这里不需要初始化直接返回成功即可
DSTATUS USER_initialize(BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{/* USER CODE BEGIN INIT */UNUSED(pdrv);return RES_OK;/* USER CODE END INIT */
}
获取磁盘状态
| 描述 | 名称 | 功能 | 
|---|---|---|
| BYTE(uint8_t) | pdrv | 磁盘编号 | 
| DSTATUS | 输出 | 错误码 | 
DSTATUS USER_status(BYTE pdrv)
成功返回
RES_OK失败返回RES_ERROR不使用返回即可
例子
DSTATUS USER_status(BYTE pdrv /* Physical drive number to identify the drive */
)
{/* USER CODE BEGIN STATUS */UNUSED(pdrv);return RES_OK;/* USER CODE END STATUS */
}
读取扇区
| 描述 | 名称 | 功能 | 
|---|---|---|
| BYTE(uint8_t) | pdrv | 磁盘编号 | 
| BYTE(uint8_t) | buff | 缓冲区 | 
| DWORD | sector | 扇区编号 | 
| UINT(uint32_t) | count | 扇区数量 | 
| DSTATUS | 输出 | 错误码 | 
DRESULT USER_read(BYTE pdrv,BYTE *buff,DWORD sector,UINT count)
示例
这个函数
W25Qxx_Read_Data输入的是FLASH的地址和byte数量,因此要乘上扇区大小
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 */W25Qxx_Read_Data(sector * USER_SECTOR_SIZE, buff, count * USER_SECTOR_SIZE);return RES_OK;/* USER CODE END READ */
}
写入扇区
| 描述 | 名称 | 功能 | 
|---|---|---|
| BYTE(uint8_t) | pdrv | 磁盘编号 | 
| BYTE(uint8_t) | buff | 缓冲区 | 
| DWORD | sector | 扇区编号 | 
| UINT(uint32_t) | count | 扇区数量 | 
| DSTATUS | 输出 | 错误码 | 
DRESULT USER_write(BYTE pdrv,const BYTE *buff,DWORD sector,UINT count)
示例
这个函数
W25Qxx_Write输入的是FLASH的地址和byte数量,因此要乘上扇区大小
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 */W25Qxx_Write(sector * USER_SECTOR_SIZE, (uint8_t *)buff, count * USER_SECTOR_SIZE, 0);return RES_OK;/* USER CODE END WRITE */
}
控制操作
| 描述 | 名称 | 功能 | 
|---|---|---|
| BYTE(uint8_t) | pdrv | 磁盘编号 | 
| BYTE(uint8_t) | cmd | 命令 | 
| void * | buff | 缓冲区 | 
| DSTATUS | 输出 | 错误码 | 
DRESULT USER_ioctl(BYTE pdrv,BYTE cmd,void *buff)
必须要响应的命令
| 描述 | 功能 | 
|---|---|
| GET_SECTOR_COUNT | 扇区数量 | 
| GET_SECTOR_SIZE | 扇区大小 单位 byte | 
| GET_BLOCK_SIZE | 区块大小 | 
例子
使用W25Q128 16MB
扇区大小为4096=4KB
扇区数为 4096 这里写4095
区块直接写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:res = RES_OK;break;case CTRL_TRIM:res = RES_OK;break;case GET_SECTOR_COUNT:*(DWORD *)buff = 4095;break;case GET_SECTOR_SIZE:*(DWORD *)buff = USER_SECTOR_SIZE;break;case GET_BLOCK_SIZE:*(DWORD *)buff = 1;break;}return res;/* USER CODE END IOCTL */
}
APIs
地址问题
根据初始化顺序,驱动器的根地址分别为
0:/1:/…比如这个例子里 SD卡的根地址是
0:/USER(可以设为FLASH等) 地址为1:/

挂载
| 描述 | 名称 | 功能 | 
|---|---|---|
| FATFS* | fs | 句柄 | 
| const TCHAR* | path | 地址 | 
| BYTE | opt | 是否立即加载(一般写1) | 
| FRESULT | 输出 | 错误码 | 
FRESULT f_mount (FATFS* fs,const TCHAR* path,BYTE opt)
挂载例子
f_mount(&hFatfs, "0:/", 1);
打开文件
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| const TCHAR* | path | 地址 | 
| BYTE | mode | 模式 | 
| FRESULT | 输出 | 错误码 | 
| 描述 | 功能 | 
|---|---|
| FA_READ | 只读 | 
| FA_WRITE | 只写 | 
| FA_OPEN_EXISTING | 如果文件存在,则打开;否则打开失败 | 
| FA_CREATE_NEW | 创建一个文件,如果文件存在,则创建失败 | 
| FA_CREATE_ALWAYS | 创建一个文件,如果文件存在,则覆盖原文件 | 
| FA_OPEN_ALWAYS | 如果文件存在,则打开,如果不存在则创建一个文件并打开 | 
可以输入
FA_READ | FA_WRITE来使用读写
FRESULT f_open (FIL* fp,const TCHAR* path,BYTE mode)
打开后光标指向开头
关闭文件
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| FRESULT | 输出 | 错误码 | 
FRESULT f_close (FIL* fp)
读文件
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| void* | buff | 缓冲区 | 
| UINT | btr | 操作数量 | 
| UINT* | br | 已操作数量 | 
| FRESULT | 输出 | 错误码 | 
FRESULT f_read (FIL* fp,void* buff,UINT btr,UINT* br)
会从光标处开始读取 指针自增
写文件
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| void* | buff | 缓冲区 | 
| UINT | btr | 操作数量 | 
| UINT* | br | 已操作数量 | 
| FRESULT | 输出 | 错误码 | 
FRESULT f_write (FIL* fp,const void* buff,UINT btw,UINT* bw)
会从光标处开始写入 指针自增
打印到文件
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| const TCHAR* | fmt | 规则格式串 | 
| ... | ... | ... | 
| int | 输出 | 写入数量 | 
int f_printf (FIL* fp,const TCHAR* fmt,...)
会从光标处开始写入 指针自增
获取文件大小
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| FSIZE_t | 输出 | 大小 | 
f_size(fp)
改变光标位置
| 描述 | 名称 | 功能 | 
|---|---|---|
| FIL* | fp | 文件 | 
| FSIZE_t | ofs | 从顶部开始的偏移 | 
| FRESULT | 输出 | 错误码 | 
FRESULT f_lseek (FIL* fp,FSIZE_t ofs)
删除文件
| 描述 | 名称 | 功能 | 
|---|---|---|
| const TCHAR* | path | 路径 | 
| FRESULT | 输出 | 错误码 | 
FRESULT f_unlink (const TCHAR* path)
检查文件是否存在
| 描述 | 名称 | 功能 | 
|---|---|---|
| const TCHAR* | path | 路径 | 
| FILINFO* | fno | 信息 | 
| FRESULT | 输出 | 不存在 FR_NO_FILE,存在FR_OK | 
FRESULT f_stat (const TCHAR* path,FILINFO* fno)