本帖最后由 zhuzhutang 于 2017-8-25 21:26 编辑
由于对文件系统比较感兴趣,所以早就想学习一下文件系统了,听说fatfs文件系“统麻雀虽小五脏俱全”,而且移植也挺方便的,于是就从这个系统下手吧。
既来之则安之!
于是找来了一块stm32f103rct6的最小系统板,再从旧手机上把里面的TF卡拆出来,装到micro sd adapter卡套上,用TF卡作为fatfs文件系统的媒介。然后对了一下micro sd adapter和TF卡的引脚关系,最后把micro sd adapter对应的引脚焊接到stm32f103rct6的SPI1引脚上,打算通过SPI口访问TF卡。硬件平台算是这么粗暴的搭建好了。
接下来就参考正点原子的 “ALIENTEK MINISTM32 实验28 SD卡实验” 这一例程,东改一下西裁一下,只保留对SD卡操作那一部分代码,跌跌撞撞的搞了差不多一天,终于是可以读TF卡的数据了,也可以对其写数据了。
OK,底层是通了,接下来就是移植fatfs系统了,于是我从官网上:
http://elm-chan.org/fsw/ff/00index_e.html,下载了最新版本的(ff13版本)源码,又在网上查了一下fatfs的移植,其实fatfs系统的移植真的是挺简单的,就只需要修改diskio.c这个与平台相关的文件,填几个函数的内容,再不就是根据自己的需要修改ffconf.h文件来获得自己想要的东西。然后再根据“ALIENTEK MINISTM32 实验29 FATFS文件系统实验”这一例程,很快就完成了移植。移植完之后把TF卡格式化一下,马上开始了测试,很顺利,挂载、打开文件、关闭文件都没问题。然后再花一天时间去实现什么删除文件、复制文件、复制文件夹啊等等乱七八糟的功能,最后再结合串口输入输出,做了一个像命令解释器这样的功能,比如像输出 “ls”,串口就会打印当前路径下的文件和文件夹。如下图所示:
后来想想,在调试阶段,对文件进行操作后,总是要把TF卡拿出来再放到电脑上看操作有没有生效,经常这样拔来拔去,心里很是不爽,于是在想,能不能在windows下操作fatfs啊, 这样就方便很多了啊。于是上网查了一下,还果真有,不过说得比较少。我就参考了这篇文章:
http://blog.csdn.net/liangjiapei/article/details/65444536。然后在windows下就可以模拟测试fatfs了。以下是本人的一些历程,今天分享出来,也算是给自己留一个笔记。
具体的操作我就不多说了,上面链接文章中已经说得挺好的了,只是有些事项我想说明一下:
1、使用
mksdcard创建一个虚拟SD卡文件时,先运行cmd,进入你放mksdcard.exe这个工具的目录,然后再执行mksdcard.exe 128M Test.img才有效。
下面贴一下代码:
main.c :
#include <stdio.h>
#include <stdlib.h>
#include "ff.h"
#include "integer.h"
#include "diskio.h"
#define PRINT_ENABLE /*是否允许打印信息*/
#if (defined PRINT_ENABLE)
#define MY_PRINTF printf
#else
void MY_PRINTF(char *format, ...)
{
}
#endif
#define ASSERT_PARAM(x) while(x==NULL){ }
FATFS * fs[1]; /*文件系统对象指针*/
FIL * file1; /*文件对象指针*/
/*------------------------------ 提示信息 -----------------------------*/
const char * tip[]=
{
"FR_OK , (0) Succeeded",
"FR_DISK_ERR, (1) A hard error occurred in the low level disk I/O layer" ,
"FR_INT_ERR, (2) Assertion failed",
"FR_NOT_READY, (3) The physical drive cannot work" ,
"FR_NO_FILE, (4) Could not find the file" ,
"FR_NO_PATH, (5) Could not find the path" ,
"FR_INVALID_NAME, (6) The path name format is invalid.",
"FR_DENIED, (7) Access denied due to prohibited access or directory full ",
"FR_EXIST, (8) Access denied due to prohibited access ",
"FR_INVALID_OBJECT, (9) The file/directory object is invalid ",
"FR_WRITE_PROTECTED,(10) The physical drive is write protect." ,
"FR_INVALID_DRIVE, (11) The logical drive number is invalid" ,
"FR_NOT_ENABLED, (12) The volume has no work area",
"FR_NO_FILESYSTEM, (13) There is no valid FAT volume" ,
"FR_MKFS_ABORTED, (14) The f_mkfs() aborted due to any problem" ,
"FR_TIMEOUT, (15) Could not get a grant to access the volume within defined period" ,
"FR_LOCKED, (16) The operation is rejected according to the file sharing policy" ,
"FR_NOT_ENOUGH_CORE, (17) LFN working buffer could not be allocated" ,
"FR_TOO_MANY_OPEN_FILES, (18) Number of open files > FF_FS_LOCK" ,
"FR_INVALID_PARAMETER (19) Given parameter is invalid" ,
} ;
/*-----------------------------------------------------------------------*/
/* 挂载设备 */
/*-----------------------------------------------------------------------*/
void MountDevice(FATFS * fs, const BYTE * str, BYTE opt)
{
FRESULT res;
ASSERT_PARAM(fs);
res = f_mount(fs, str, opt);
if(res==RES_OK)
{
MY_PRINTF("Mount success!
");
MY_PRINTF("file csize is %d.
", fs->csize);
MY_PRINTF("file fsize is %d.
", fs->fsize);
MY_PRINTF("file n_fats is %d.
", fs->n_fats);
}
else
{
MY_PRINTF("Mount fail!
%s
",tip[res]);
}
}
int main(void)
{
FRESULT res;
UINT fre_clust=0;
UINT bw=0, br=0, num2read=0;
UINT pos=0;
const BYTE * str = "1234567890!";
BYTE * pstr;
/**------------------ 为文件系统对象和文件对象申请内存空间 -------------------**/
file1 = malloc(sizeof(FIL));
if(file1!=NULL)
{
MY_PRINTF("Malloc FIL space success!
");
}
else
{
MY_PRINTF("Malloc FIL space fail!
");
}
fs[0] = malloc(sizeof(FATFS));
if(fs[0]!=NULL)
{
MY_PRINTF("Malloc FATFS space success!
");
}
else
{
MY_PRINTF("Malloc FATFS space fail!
");
}
/**------------------ 挂载一个设备 -------------------**/
MountDevice(fs[0], "0:", 1);
/**----------------------- 打开文件 ------------------**/
res = f_open(file1, "0:/zrt.txt", FA_OPEN_ALWAYS | FA_WRITE);
if(res==RES_OK)
{
MY_PRINTF("Open file success!
");
}
else
{
MY_PRINTF("Open file fail!
%s
",tip[res]);
}
/*-------------------------- 写文件 -------------------------*/
//f_lseek(file1, f_size(file1)); /*定位到文件的结尾,从文件结尾开始写数据*/
res = f_write(file1, str, strlen(str), &bw);
if(res==RES_OK)
{
MY_PRINTF("Write file success!
");
}
else
{
MY_PRINTF("Write file fail!
%s
",tip[res]);
}
/* 关闭打开的文件。注意:如果对文件进行了修改,一定要关闭文件修改才能起效,如果做了修改不关闭文件,用UltraISO打开SD卡镜像时内容是没有同步更新的 */
res = f_close(file1);
if(res==RES_OK)
{
MY_PRINTF("close file success!
");
}
else
{
MY_PRINTF("close file fail!
%s
",tip[res]);
}
/**----------------------- 打开文件 ------------------**/
res = f_open(file1, "0:/zrt.txt", FA_OPEN_EXISTING | FA_READ);
if(res==RES_OK)
{
MY_PRINTF("Open file success!
");
}
else
{
MY_PRINTF("Open file fail!
%s
",tip[res]);
}
/***-------------------------- 读文件 ------------------------**/
pstr = malloc(FF_MAX_SS);
MY_PRINTF("This file size is %d byte.
",f_size(file1)); /*打印文件大小*/
while(res == RES_OK)
{
res = f_read(file1, pstr, FF_MAX_SS, &br); /*一次读的大小不能超过FF_MAX_SS,不然会造成数组越界,在free内存时出现异常*/
for(num2read=0; num2read<br; num2read++)
{
//putchar(pstr[num2read]);
MY_PRINTF("%c",pstr[num2read]);
}
if(br == 0)
{
break;
}
}
free(pstr); /** 释放pstr所占内存 **/
MY_PRINTF("
");
/*------------------------------------- 关闭打开的文件 ------------------------------*/
res = f_close(file1);
if(res==RES_OK)
{
MY_PRINTF("close file success!
");
}
else
{
MY_PRINTF("close file fail!
%s
",tip[res]);
}
/*----------- 释放空间 -------------*/
free(file1);
free(fs[0]);
return 0;
}
diskio.c :
#include <Windows.h>
#include <stdio.h>
#include "diskio.h" /* FatFs lower layer API */
#define SECTOR_SIZE 512
FILE *fpImg = 0; /*FILE是系统自带的结构体*/
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if (pdrv == 0)
{
return RES_OK;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if (pdrv == 0)
{
if (!fpImg)
{
fpImg = fopen("./MMC_SD.img", "rb+"); /*打开本目录下的MMC_SD.img文件,这里就是把SD卡的镜像文件挂载进来*/
if (fpImg == NULL)
{
return STA_NOINIT;
}
}
return RES_OK;
}
return RES_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
UINT i = 0;
BYTE *pOut;
if (pdrv == 0)
{
pOut = buff;
if (!fpImg)
return RES_ERROR;
fseek(fpImg, SECTOR_SIZE*sector, SEEK_SET); /*定位到文件所在的扇区,SEEK_SET表示开始位置*/
for (i = 0; i<count; i++) /*读取扇区数据*/
{
fread(pOut, SECTOR_SIZE, 1, fpImg);
pOut = pOut + SECTOR_SIZE;
}
return RES_OK;
}
return RES_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
UINT i = 0;
const BYTE *pOut;
DRESULT result;
if (pdrv == 0)
{
pOut = buff;
if (!fpImg)
{
return RES_ERROR;
}
fseek(fpImg, SECTOR_SIZE*sector, SEEK_SET); /*定位到文件所在的扇区,SEEK_SET表示开始位置*/
for (i = 0; i < count; i++)
{
fwrite(pOut, SECTOR_SIZE, 1, fpImg);
pOut = pOut + SECTOR_SIZE;
}
result = RES_OK;
}
return result;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
switch (cmd)
{
default:
break;
}
return RES_OK;
}
DRESULT get_fattime(void)
{
return RES_OK;
}
最后,附上源码。
pc_fatfs.zip
(2.77 MB, 下载次数: 112)
2017-8-25 21:26 上传
点击文件名下载附件
最后的最后,新手求罩!
还在学习当中,请多多指教!
一周热门 更多>