序号 | 分类 | 文件名 | 功能 |
1 | 与平台无关 | ffconf.h | FATFS配置文件 |
2 | ff.h | FATFS和应用模块公用的包含文件 | |
3 | ff.c | FATFS模块 | |
4 | diskio.h | FATFS和disk I/O模块公用的包含文件 | |
5 | interger.h | 数据类型定义 | |
6 | option | 可选的外部功能(比如支持中文等) | |
7 | 与平台有关(需要用户提供) | diskio.c | FATFS和disk I/O模块接口层文件 |
序号 | 配置名 | 内容 |
1 | _FS_TINY | 这个选项在R0.07版本中开始出现,以前是以独立的C文件出现(FATFS和Tiny FATFS),有了这个选项后,两者合在一起了,使用起来更方便。我们使用FATFS,所以设置为0即可。 |
2 | _FS_READONLY | 配置是否只读。 本章需要读写都用,所以设置为0即可。 |
3 | _USE_STRFUNC | 配置是否支持字符串操作,比如f_putc,f_puts等。 本章用到,所以设置为1。 |
4 | _USE_MKFS | 定时是否使能格式化。 本章用到,所以设置为1。 |
5 | _USE_FASTSEEK | 使能快速定位。 本章需要快速定位,设置为1。 |
6 | _USE_LABEL | 设置是否支持磁盘盘符(磁盘名字)读取与设置。 本章用到,可以读取或设置磁盘的名字。使能,设置为1。 |
7 | _CODE_PAGE | 设置语言类型,包括很多选项(见FATFS官网说明),我们设置为936,即简体中文(GBK码,需要c936.c文件支持,该文件在option文件夹) |
8 | _USE_LFN | 设置是否支持长文件名(还需要_CODE_PAGE支持),取值范围为0~3。 0:不支持; 1~3:支持,但存储的地方不一样,我们使用3,通过ff_memalloc函数来动态分配长文件名的存储区。 |
9 | _VOLUMES | 设置FATFS支持的逻辑设备数目。 我们设置为2,即支持2个设备。 |
10 | _MAX_SS | 扇区缓冲的最大值,一般为512。 |
diskio.c | disk_initialize() |
disk_status() | |
disk_read() | |
disk_write() | |
disk_ioctl() | |
get_fattime() |
函数1名称 | disk_initialize |
函数原型 | DSTATUS disk_initialize(BYTE Drive) |
功能描述 | 初始化磁盘驱动器 |
函数参数 | Drive:指定要初始化的逻辑驱动器号,即盘符,应当取值0~9. |
返回值 | 磁盘操作状态。(磁盘状态的细节信息,参考disk_status函数) |
所在文件 | ff.c |
示例 | disk_initialize(0);//初始化驱动器0 |
注意事项 | 函数初始化一个逻辑磁盘驱动器为读/写做准备,成功时,返回值的STA_NOINIT标志被清零; 应用程序不应该调用此函数,否则卷上的FAT结构可能被破坏; 如果需要重新初始化文件系统,可以使用f_mount函数; 在FatFs模块的上卷注册处理时,调用该函数可控制设备的改变; 此函数在FatFs挂在卷时调用,应用程序不应该在FatFs活动时使用此函数。 |
函数2名称 | disk_status |
函数原型 | DISTATUS disk_status(BYTE Drive) |
功能描述 | 返回当前的磁盘驱动器的状态 |
函数参数 | Drive:指定要确认的逻辑驱动器号,即盘符,应当取值0~9 |
返回值 | 磁盘状态返回下列标志的组合,FatFs只使用STA_NOINIT和STA_PROTECTED。 STA_NOINIT:表明磁盘驱动未初始化,下面列出了该标志置位或清零的原因: 置位:系统复位,磁盘被移除和磁盘初始化函数失败; 清零:磁盘初始化函数成功。 STA_NODISK:表明磁盘驱动器没有设备,安装磁盘驱动器后总为0。 STA_PROTECTED:表明设备被写保护,不支持写保护的设备总为0,当STA_NODISK置位时非法。 |
所在文件 | ff.c |
示例 | disk_status(0);//获取驱动器0的状态 |
注意事项 |
函数3名称 | disk_read |
函数原型 | DRESULT disk_read(BYTE Drive, BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount) |
功能描述 | 从磁盘驱动器上读取扇区 |
函数参数 | Drive:指定逻辑驱动器号,即盘符,应当取值0~9; Buffer:指向储存读取数据字节数组的指针(需要为所读取字节数的大小,扇区统计的扇区大小的需要的); 注:FatFs指定的内存地址不总是字对齐的,如果硬件不支持不对其的数据传输,则函数里需要进行处理; SectorNumber:指定起始扇区的逻辑块(LBA)上的地址; SectorCount:指定要读取的扇区数,取值1~128。 |
返回值 | RES_OK(0):函数成功 RES_ERROR:读操作期间产生了任何错误且不能恢复它 RES_PARERR:非法参数 RES_NOTRDY:磁盘驱动器没有初始化 |
所在文件 | ff.c |
函数4名称 | disk_write |
函数原型 | DRESULT disk_write(BYTE Drive, const BYTE * Buffer, DWORD SectorNumber, BYTE SectorCount) |
功能描述 | 向磁盘写入一个或多个扇区 |
函数参数 | Drive:指定逻辑驱动器号,即盘符,应当取值0~9; Buffer:指向要写入字节数组的指针; 注:FatFs指定的内存地址并不总是字节对齐的,如果硬件不支持不对齐的数据传输,则函数里面需要进行处理。 SectorNumber:指定起始扇区的逻辑块(LBA)上的地址 SectorNumber:指定要写入的扇区数,取值1~128 |
返回值 | RES_OK(0):函数成功 RES_ERROR:读操作期间产生了任何错误且不能恢复它 RES_WRPRT:媒体被写保护 RES_PARERR:非法参数 RES_NOTRDY:磁盘驱动器没有初始化 |
所在文件 | ff.c |
注意事项 | 只读配置中不需要此函数 |
函数5名称 | disk_ioctl |
函数原型 | DRESULT disk_ioctl (BYTE Drive, BYTE Command, void * Buffer) |
功能描述 | 控制设备指定特性和除了读写外的杂项功能 |
函数参数 | Drive :指定逻辑驱动器号,即盘符,取值0~9; Command:指定命令代码; Buffer :指向参数缓冲区的指针,取决于命令代码,不使用时,指定一个NULL指针 |
返回值 | RES_OK(0) :函数成功 RES_ERROR :读操作期间产生了任何错误且不能恢复它 RES_PARERR:非法参数 RES_NOTRDY:磁盘驱动器没有初始化 |
所在文件 | ff.c |
注意事项 | CTRL_SYNC :确保磁盘驱动器已经完成了写处理,当磁盘I/O有一个写回缓存, 立即刷新原扇区,只读配置下不适用此命令。 GET_SECTOR_SIZE :返回磁盘扇区大小,只用于f_mkfs(); GET_SECTOR_COUNT :返回可利用的扇区数,_MAX_SS >= 1024时可用; GET_BLOCK_SIZE :获取擦除块大小,只用于f_mkfs(); CTRL_ERASE_SECTOR:强制擦除一块的扇区,_USE_REASE > 0时可用。 |
函数6名称 | get fattime |
函数原型 | DWORD get_fattime() |
功能描述 | 获取当前时间 |
函数参数 | 无 |
返回值 | 当前时间以双字值封装返回。 位域如下: bit31:25 年(0~127)(从1980开始) bit24:21 月(1~12) bit20:16 日(1~31) bit15:11 小时(0~23) bit10:5 分钟(0~59) bit4:0 秒(0~29) |
所在文件 | ff.c |
注意事项 | get_fattime函数必须返回一个合法的时间即使系统不支持实时时钟,如果返回0, 文件没有一个合法的时间:只读配置下无需此函数。 |
#define SD_CARD 0 //SD卡,卷标为0
#define EX_FLASH 1 //外部Flash,卷标为1
#define FLASH_SECTOR_SIZE 512
//对于W25Q128
//前12M字节给FatFs使用,12M字节后,用于存放字库,字库占3.09M,剩余的给客户自己使用
u16 FLASH_SECTOR_COUNT = 2048*12; //W25Q128前12M字节
#define FLASH_BLOCK_SIZE 8 //每个BLOCK有8个扇区
//获得磁盘状态
DSTATUS disk_status(BYTE pdrv) //Physical drive number to identify the drive
{
return RES_OK;
}
//初始化磁盘
DSTATUS disk_initialize(BYTE pdrv) //Physical drive number to identify the drive
{
u8 res = 0;
switch(pdrv)
{
case SD_CARD: //SD卡
res = SD_Init(); //SD卡初始化
break;
case EX_FLASH: //外部Flash
W25QXX_Init();
FLASH_SECTOR_COUNT = 2048*12; //前12M字节给FATFS占用
break;
default:
res = 1;
}
if(res)
return STA_NOINIT;
else
return 0; //初始化成功
}
//读扇区
//pdrv :磁盘编号0~9
//*buffer:数据接收缓冲首地址
//sector :扇区地址
//count :需要读取的扇区数
DRESULT disk_read(BYTE pdrv, //physical drive number 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
{
u8 res = 0;
if(!count)
return RES_PARERR; //count不能等于0,否则返回参数错误
switch(pdrv)
{
case SD_CARD: //SD卡
res = SD_ReadDisk(buff, sector, count);
while(res) //读出错
{
SD_Init(); //重新初始化SD卡
res = SD_ReadDisk(buff, sector, count);
//printf("sd rd error:%d\r\n", res);
}
break;
case EX_FLASH: //外部Flash
for(; count > 0; count--)
{
W25QXX_Read(buff, sector*FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE)
sector++;
buff += FLASH_SECTOR_SIZE;
}
res = 0;
break;
default:
res = 1;
}
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
if(res == 0x00)
return RES_OK;
else
return RES_ERROR;
}
//写扇区
//pdrv :磁盘编号0~9
//*buffer:发送数据首地址
//sector :扇区地址
//count :需要写入的扇区数
#if _USE_WRITE
DRESULT disk_write(BYTE pdrv, //physical drive number to identify the drive
const BYTE *buff, //Data buffer to store read data
DWORD sector, //Sector address in LBA
UINT count) //Number of sectors to write
{
u8 res = 0;
if(!count)
return RES_PARERR; //count不能等于0,否则返回参数错误
switch(pdrv)
{
case SD_CARD: //SD卡
res = SD_WriteDisk((u8*)buff, sector, count);
while(res) //写出错
{
SD_Init(); //重新初始化SD卡
res = SD_WriteDisk((u8*)buff, sector, count);
//printf("sd wr error:%d\r\n", res);
}
break;
case EX_FLASH: //外部Flash
for(; count > 0; count--)
{
W25QXX_Write((u8*)buff, sector*FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE);
sector++;
buff += FLASH_SECTOR_SIZE;
}
res = 0;
break;
default:
res = 1;
}
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
if(res == 0x00)
return RES_OK;
else
return RES_ERROR;
}
#endif
//其他表参数的获取
//pdrv:磁盘编号0~9
//ctrl:控制代码
//*buff:发送/接收缓冲区指针
#if _USE_IOCTL
DRESULT disk_ioctl(BYTE pdrv, //Physical drive number(0...)
BYTE cmd, //Control code
void * buff) //Buffer to send/receive control data
{
DRESULT res;
if(pdrv == SD_CARD) //SD卡
{
switch(cmd)
{
case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_SIZE:
*(DWORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = SDCardInfo.CardBlockSize;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = SDCardInfo.CardCapacity/512;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
}
else if(pdrv == EX_FLASH) //外部FLASH
{
switch(cmd)
{
case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_SIZE:
*(WORD*)buff = FLASH_SECTOR_SIZE;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = FLASH_BLOCK_SIZE;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = FLASH_SECTOR_COUNT;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
}
else
res = RES_ERROR; //其他不支持
return res;
}
#endif
//获取时间
//User defined function to give a current time to fatfs module
//当前时间以双字值封装返回。
//位域如下:
//bit31:25 年(0~127)(从1980开始)
//bit24:21 月(1~12)
//bit20:16 日(1~31)
//bit15:11 小时(0~23)
//bit10:5 分钟(0~59)
//bit4:0 秒(0~29)
DWORD get_fattime(void)
{
return 0;
}
//动态分配内存
void *ff_memcalloc(UINT size)
{
return (void*)mymalloc(SRAMIN, size);
}
//释放内存
void ff_memfree(void * mf)
{
myfree(SRAMIN, mf);
}
int main()
{
u32 total, free;
u8 t = 0; u8 res = 0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
usmart_dev.init(72); //初始化USMART
LED_init();
KEY_init();
LCD_init();
W25QXX_init(); //初始化W25Q128
my_mem_init(SRAMIN); //初始化内部内存池
POINT_COLOR = RED;
LCD_ShowString(30,50,200,16,16,"WarShip STM32");
LCD_ShowString(30,70,200,16,16,"FATFS TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2015/1/20");
LCD_ShowString(30,130,200,16,16,"Use USMART for test");
while(SD_Init())//检测不到 SD 卡
{
LCD_ShowString(30,150,200,16,16,"SD Card Error!"); delay_ms(500);
LCD_ShowString(30,150,200,16,16,"Please Check! "); delay_ms(500);
LED0=!LED0;//DS0 闪烁
}
exfuns_init(); //为fatfs相关变量申请内存
f_mount(fs[0], "0:", 1); //挂载SD卡
res = f_mount(fs[1], "1:", 1); //挂载FLASH
if(res == 0x0D) //FLASH磁盘,FAT文件系统错误,重新格式化FLASH
{
LCD_ShowString(30,150,200,16,16,"Flash Disk Formatting...");//格式化 FLASH
res = f_mkfs("1:", 1, 4096); //格式化FLASH, 1, 盘符;1,不需要引导区,8个扇区为1镞
if(res == 0)
{
f_setlabel((const TCHAR*)"1:ALIENTEK"); //设置Flash磁盘名:ALIENTEK
LCD_ShowString(30,150,200,16,16,"Flash Disk Format Finish");//格式化完成
}
else
LCD_ShowString(30,150,200,16,16,"Flash Disk Format Error ");//格式化失败
delay_ms(1000);
}
LCD_Fill(30,150,240,150+16,WHITE); //清除显示
while(exf_getfree("0", &total, &free)) //得到SD卡的总容量和剩余容量
{
LCD_ShowString(30,150,200,16,16,"SD Card Fatfs Error!");
delay_ms(200);
LCD_Fill(30,150,240,150+16,WHITE);//清除显示
delay_ms(200);
LED0=!LED0;//DS0 闪烁
}
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,150,200,16,16,"FATFS OK!");
LCD_ShowString(30,170,200,16,16,"SD Total Size: MB");
LCD_ShowString(30,190,200,16,16,"SD Free Size: MB");
LCD_ShowNum(30+8*14,170,total>>10,5,16); //显示 SD 卡总容量 MB
LCD_ShowNum(30+8*14,190,free>>10,5,16); //显示 SD 卡剩余容量 MB
while(1)
{
t++;
delay_ms(200);
LED0=!LED0;
}
}
(void*)mf_mount, "u8 mf_mount (u8* path,u8 mt)",
(void*)mf_open, "u8 mf_open (u8*path,u8 mode)",
(void*)mf_close, "u8 mf_close (void)",
(void*)mf_read, "u8 mf_read (u16 len)",
(void*)mf_write, "u8 mf_write (u8*dat,u16 len)",
(void*)mf_opendir, "u8 mf_opendir (u8* path)",
(void*)mf_closedir, "u8 mf_closedir (void)",
(void*)mf_readdir, "u8 mf_readdir (void)",
(void*)mf_scan_files,"u8 mf_scan_files (u8 * path)",
(void*)mf_showfree, "u32 mf_showfree (u8 *drv)",
(void*)mf_lseek, "u8 mf_lseek (u32 offset)",
(void*)mf_tell, "u32 mf_tell (void)",
(void*)mf_size, "u32 mf_size (void)",
(void*)mf_mkdir, "u8 mf_mkdir (u8*pname)",
(void*)mf_fmkfs, "u8 mf_fmkfs (u8* path,u8 mode,u16 au)",
(void*)mf_unlink, "u8 mf_unlink (u8 *pname)",
(void*)mf_rename, "u8 mf_rename (u8 *oldname,u8* newname)",
(void*)mf_getlabel, "void mf_getlabel (u8 *path)",
(void*)mf_setlabel, "void mf_setlabel (u8 *path)",
(void*)mf_gets, "void mf_gets (u16 size)",
(void*)mf_putc, "u8 mf_putc (u8 c)",
(void*)mf_puts, "u8 mf_puts (u8*c)",