ImageVerifierCode 换一换
格式:DOC , 页数:5 ,大小:35KB ,
资源ID:1356517      下载积分:10 金币
验证码下载
登录下载
邮箱/手机:
图形码:
验证码: 获取验证码
温馨提示:
支付成功后,系统会自动生成账号(用户名为邮箱或者手机号,密码是验证码),方便下次登录下载和查询订单;
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/1356517.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请。


权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:4009-655-100;投诉/维权电话:18658249818。

注意事项

本文(FatFs使用流程.doc)为本站上传会员【可****】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

FatFs使用流程.doc

1、一、读文件流程。 1、程序结构 res = f_mount(0, &fs); res = f_open(&file, "data.txt", FA_OPEN_EXISTING | FA_READ); while(1) { if(fgets(data, sizeof(data), &file)==NULL) { break; } prints(data); } f_close(&file); 总共四个与文件系统相关的函数,下面就沿着函数执行路径去探索一下。 2、f_mount(0,

2、fs)的执行 参数0是卷号,就像电脑上的CDE盘等。fs是一个未初始化的一个文件系统对象,其定义在此:FATFS fs。这个函数好像就做了两个个事,使全局文件系统指针FatFS指向fs对象,并使fs.fstype=0。 3、f_open(&file, "data.txt", FA_OPEN_EXISTING | FA_READ)的执行 参数&file是提供一个文件对象指针,打开文件过程中获得的一些信息都填入这个结构体。FA_OPEN_EXISTING | FA_READ表示要打开和读取相应的文件。源程序如下: FRESULT f_open ( FIL *fp

3、 /* fp就指向传入的对象file */ const char *path, /*path指向data.txt的地址*/ BYTE mode /* Access mode and file open mode flags */ ) { DIR dj; 目录对象 BYTE *dir; 目录项指针 char fn[8+3+1]; 8.3文件名。 // 程序开头定义了这么三个变量,007c版本中由于支持长文件名,最好一个改为NAMEBUF(sf

4、n, lfn)。 fp->fs = NULL; 每个文件对象都指向具体的文件系统,这里先清0 auto_mount(&path, &dj.fs, (BYTE)(mode) ); //这个函数看来很关键了。旧版的函数没有中间这个参数。 Path本来就是一个指针,&path就是一个指向指针的指针,&dj.fs因为dj对象还未设置,这个指针传入应该是供auto_mount函数设置的。 4、auto_mount(&path, &dj.fs, (BYTE)(mode) )的执行 先分析旧版的: FRESULT auto_mount ( /* FR_OK(0

5、): successful, !=0: any error occured */ const char **path, /* Pointer to pointer to the path name (drive number) */ BYTE chk_wp /* !=0: Check media write protection for write access) { DWORD bootsect, fatsize, totalsect, maxclust; const char *p = *p

6、ath; //指针p现在就指向文件名字符串了。 FATFS *fs; memset(fs, 0, sizeof(FATFS)); /*将全局文件系统结构清0 */ stat = disk_initialize(0); /*磁盘初始化程序,在这里调用的 */ fmt = check_fs(bootsect = 0); /* Check sector 0 as an SFD format */ 这里主要是调用了check_fs(bootsect = 0)函数检测是否存在FA

7、T文件系统。 下面是源代码: BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record or error */ DWORD sect /* Sector# to check if it is an FAT boot record or not */ ) { FATFS *fs = FatFs; if (disk_read(0, fs->win, sect, 1) != RES_OK) /

8、 Load boot record */ return 2; if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /*Check record signature */ return 2; if (!memcmp(&fs->win[BS_FilSysType], "FAT", 3))/* Check FAT signature */ return 0; if (!memcmp(&fs->win[BS_FilSysT

9、ype32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80)) return 0; return 1;} 这个函数的主要操作是:将磁盘的0扇区读入fs->win【】扇区缓冲。并对其中的特殊位置进行检验。如果读入错误或者末尾不是55AA,返回2。如果确实是FAT文件系统返回0。如果返回1可能是主引导扇区,继续从分区引导扇区读取。 auto_mount继续往下执行: fatsize = LD_DWORD(&fs->win[BPB_FATSz32]); fs->sec

10、ts_fat = (CLUST)fatsize; //每个FAT表的扇区数目 fs->n_fats = fs->win[BPB_NumFATs]; /* FAT表的个数 */ fatsize *= fs->n_fats; /* (Number of sectors in FAT area) */ fs->fatbase = bootsect + LD_WORD(&fs->win[BPB_RsvdSecCnt]); /* FAT start se

11、ctor (lba) */FAT表开始于开始扇区+保留扇区。 fs->csize = fs->win[BPB_SecPerClus]; /* 每个簇的扇区数目 */ fs->n_rootdir = LD_WORD(&fs->win[BPB_RootEntCnt]); /* Nmuber of root directory entries */ totalsect = LD_DWORD(&fs->win[BPB_TotSec32]); fs->max_clust = maxclust;

12、 fmt = FS_FAT32; if (fmt == FS_FAT32) fs->dirbase = LD_DWORD(&fs->win[BPB_RootClus]); fs->database = fs->fatbase + fatsize + fs->n_rootdir / 16; /* Data start sector (lba) fs->free_clust = (CLUST)0xFFFFFFFF; //以上代码主要是根据引导扇区里的数据,填充文件系统对象结构体的信息:包括FAT表大小、数目、根目录区

13、起始地址、数据区起始扇区、文件系统类型等等。后面还有一些代码,也是做同样工作的,这里就不再叙述了。 函数下面回到f_open继续执行。 Auto_mount函数早期有个转折,如果文件系统类型已经定义,则直接返回,后续代码不会执行。 5、f_open()执行完auto_mount()后 下一个函数: trace_path(&dj, fn, path, &dir); /* Trace the file path */ 这个函数里面只有path指向文件路径,其它三个都是未经初始化的指针,应该都是在这个函数里面进行设置。Dj是目录结构体,fn是8.3文件名数组,dir是指向fs扇区缓冲

14、里当前文件目录项的指针。 从函数名称和参数可以推断出它的主要功能是将文件名从路径中提取出来,并转变成从标准8.3格式,同时找到文件所在目录,并将目录扇区读入文件系统缓冲区,依据文件目录项的信息填充dj结构体。 新的007c代码中已经改成了follow_path(); 以下是源代码: FRESULT trace_path ( DIR *dj, char *fn,const char *path, BYTE **dir ) { dj->fs = fs; clust = fs->dirbase; if (fs->fs_type

15、 == FS_FAT32) { dj->clust = dj->sclust = clust; //目录项的当前簇和开始簇都指向根目录区 dj->sect = clust2sect(clust);} //从簇号得到相应的扇区。 dj->index = 0; //目录索引项先初始化为0 for (;;) { ds = make_dirfile(&path, fn); /* Get a paragraph into fn[] */ make_di

16、rfile(&path, fn)功能是获得文件名,跟进源代码看一看:有些地方还不是太清晰,但大概意思是抽取目录。有效格式如:/dir1/dir11/file1.txt等,执行该函数后fn[]应该=“dir1***.***”,性质是目录。 move_window(dj->sect);//这个函数是将对应簇读到文件系统缓冲区。 dptr = &fs->win[(dj->index & 15) * 32]; //这是一个目录项的指针。 memcmp(&dptr[DIR_Name], fn, 8+3); //将文件名或目录名与当前目录项比较,看是不是需要打开的文件或者目录。 如果不是,则取

17、出下一个目录项:next_dir_entry(dj);然后进行循环。没有找到的。外层循环继续把目录剥离,往下寻找。最终找到对应的文件。 trace_path()函数返回以后,f_open()函数主要根据trace_path所得到的信息填充file文件结构体。比如: fp->dir_sect = dj.fs->winsect; /* 指向目录项所在扇区 */ fp->dir_ptr = dir; //指向扇区中对应目录项的指针 fp->flag = mode; /* F

18、ile access mode */ fp->org_clust = /* File start cluster */ ((DWORD)LD_WORD(&dir[DIR_FstClusHI]) << 16) | LD_WORD(&dir[DIR_FstClusLO]); fp->fsize = LD_DWORD(&dir[DIR_FileSize]); /* File size */ fp->fptr = 0; fp-

19、>csect = 255; /* 文件读写指针为0 */ fp->fs = dj.fs; fp->id = dj.fs->id; /* Owner file system object of the file */ f_open()到此执行结束。 6、fgets(data, sizeof(data), &file)的执行 该函数的主要参数是数据缓冲区data,和文件结构描述符file。跟进源代码: while (i < len - 1) { /* Read bytes until buf

20、fer gets filled */ f_read(fil, p, 1, &rc); if (rc != 1) break; /* Break when no data to read */ if (*p == '\r') continue; /* Strip '\r' */ i++; if (*p++ == '\n') break; /* Break when reached end of line *

21、/ } 主要是调用f_read函数,一个字节一个字节的读进来,如果遇到\r\n,则读入结束,正确返回buf缓冲区指针;不正确返回0. 所以读文件的重点在f_read()函数。 7、f_read(fil, p, 1, &rc)函数的分析 读函数中第一个关键语句:remain = fp->fsize - fp->fptr; //文件大小减去当前位置,得到剩下的字节数。if (btr > remain) btr = (UINT)remain;//如果要读的字节数大于剩余字节数,则调整。 举个例子,从文件头开始读5128个字节,共占据11个扇区。一

22、簇以8个扇区计算。 for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fp->fptr % 512U) == 0) { /*读初始指针位于扇区位于边界 */ sect = clust2sect(fp->curr_clust) + fp->csect;

23、/* 簇的第一个扇区 */ cc = btr / 512U; /* cc="10"表示多于一个扇区, */ if (cc) { /* Read maximum contiguous sectors directly */ if (fp->csect + cc > fp->fs->csize) /* 多于一个簇 */ cc =

24、 fp->fs->csize - fp->csect; //暂时先读一个簇。 if (disk_read(0, rbuff, sect, (BYTE)cc) != RES_OK) goto fr_error; fp->csect += (BYTE)cc; /* 移动到下一个簇 */ rcnt = 512U * cc; /* Numb

25、er of bytes transferred */ continue; 第二次读时,要执行下面语句:第二次要读两个扇区 if (fp->csect >= fp->fs->csize) { /* 移动到下一簇 */ clust = (fp->fptr == 0) ? /* On the top of the file? */

26、 fp->org_clust : get_cluster(fp->curr_clust); if (clust < 2 || clust >= fp->fs->max_clust) goto fr_error; fp->curr_clust = clust; /*更新当前簇 */ fp->csect = 0; /* 簇内扇区号变为0 */

27、 } 第二次读时额外执行的语句。 } fp->csect++; /* 这个在第三次读时也会执行 */ }//往下语句也会在第三次读时执行。 sect = clust2sect(fp->curr_clust) + fp->csect - 1; /* 如果文件读写指针不在扇区边界,为了读到数据,必须往前走一个扇区 */ if (!move_w

28、indow(sect)) goto fr_error; /* Move sector window */ rcnt = 512U - (fp->fptr % 512U); * Get partial sector from sector window */ if (rcnt > btr) rcnt = btr; memcpy(rbuff, &fp->fs->win[fp->fptr % 512U], rcnt); } 8、f_close() 主要

29、做了两个工作:(1)res = f_sync(fp);将文件的改动写入,同时调用函数sync()将文件系统变化写入文件系统相应信息区域。(2)fp->fs=0,将文件关闭。 //-------------------------------------------------------------------------- 二、写文件流程分析 1、写文件程序结构。 res = f_open(&file, "331.txt", FA_CREATE_ALWAYS | FA_WRITE); res = f_write(&file, data, 512, &br);

30、 f_close(&file); 2、函数f_open(&file, "331.txt", FA_CREATE_ALWAYS | FA_WRITE)的执行 仍然是打开文件,但是以创建和写的方式打开,其执行与读方式的打开就稍有不同。以下是写部分的操作源代码: 先执行函数reserve_direntry(&dj, &dir); 这个函数的作用是通过dj目录对象在相应目录的簇里查找一个空闲目录项,并用dir指向它。并设置该文件目录项的属性等。 3、f_write(&file, data, 512, &br);函数的执行 这个函数执行文件写

31、入操作,file是文件信息结构体:包括它对应的文件系统结构体指针、目录项扇区号、文件对用的起始簇号、当前簇号、当前扇区号、文件对象写指针。有了这些信息,就好操作文件。Data是写入数据的缓冲区,512是要写的数据个数,br是写入成功的个数(这个是返回值)。部分源代码如下: cc = btw / 512U; /* When remaining bytes >= sector size, */ if (cc) { * Write maximum contiguous sectors directly */

32、 if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */ cc = fp->fs->csize - fp->csect; if (disk_write(0, wbuff, sect, (BYTE)cc) != RES_OK) 实际操作与读文件差不多,只是在写入数目操作本簇的时候,有这个操作,clust = create_chain(fp->curr_clust)文件系统会分配一个新的簇。

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服