完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近学习fat32,看了不少资料,疑团未解,望高手们不吝赐教。
(1)if(cluster==FAT_TAB.Fat_Base_Tab[t])//是在BASE,但是是第一个 if(cluster==FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)//是在BASE,但是是最后一个了 这是怎么判断出来的呢?解释我不出来为什么是点一个或是最后一个? (2) for(t=0;t if(cluster<=(FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)&&cluster>=FAT_TAB.Fat_Base_Tab[t])break;//在这个BASE内 } 这个for循环的作用是什么啊?找出与当前簇相邻的簇? (3) return FAT_TAB.Fat_Base_Tab[t-1]+FAT_TAB.Fat_Base_Len[t-1]-1;//上一个簇号 return FAT_TAB.Fat_Base_Tab[t+1];//下一个簇号 为什么返回值不是 return FAT_TAB.Fat_Base_Tab[t-1],return FAT_TAB.Fat_Base_Tab[t+1]; //或是return FAT_TAB.Fat_Base_Tab[t-1]+FAT_TAB.Fat_Base_Len[t-1]-1;//上一个簇号 return FAT_TAB.Fat_Base_Tab[t-+1]+FAT_TAB.Fat_Base_Len[t+1]+1;//下一个簇号 请不要回复我再去看书或是查相关的资料,如果不能在此地得到答案,我回去做这些工作的。 |
|
相关推荐
4个回答
|
|
你这个是在看我那个利用文件系统的连贯性进行压缩的那部分吧?
|
|
|
|
以下是很久以前写的一点文字:
这两天在弄VS1053的mp3,VS1053可以支持所有格式的快进和快退,虽然VS1053很强大,但是如果单片机跟不上,那么其强大的优势就体现不出来.现在我的已经可以正常和快速播放各种VS1053支持的格式(MIDI未测).今天在弄VS1053的快进和快退,但是由于文件系统的链式结构的特殊性,实现向下访问很容易,但是如果要实现向上访问,那么久比较麻烦了.具体原因大家如果了解FAT结构就清楚了. 现在要做快进怎么办呢?一般的方法就是把整个文件的FAT表拷贝下来.这样虽然可以随机访问,但是如果文件比较大的话,就会遇到RAM不够的问题了.假设我们一个簇是30K大小,那么一首30M大小的歌曲 要1000个簇,我们也就需要1000个u32型数据来存储这个链表.占用了4K的sram.对于AVR来说,这无疑是不行的.当然对于我用的STM32还是可以的. 但是如果一个300M的歌曲合集呢?所以这种方法耗资源严重. 仔细分析FAT的链式结构,可以得出结论:后一个簇一般会大于前一个簇,,而且一般是大1.根据这个原理,这样我们就可以用较少的RAM来COPY整个FILE的Cluster了. 以下是我今天想到的方法: //tinyFAT表结构 //利用FAT表的一致性,一般后一个簇比前一个簇只是大一. //将FAT表压缩成小的tinyFAT表 typedef __packed struct { #define Fat_Table_Size 10 //tinyFAT表大小 #define Fat_Head_Size 10 //tinyFAT表头大小 u8 Fat_Head_Pos; //tinyFAT表的上一个表头位置 u32 Fat_Base_Head[Fat_Head_Size];//tinyFAT表的 表头数组 u32 Fat_Base_Tab[Fat_Table_Size];//文件的tinyFAT基址表 u16 Fat_Base_Len[Fat_Table_Size];//基址偏移量 u8 Fat_Over; //文件的tinyFAT表是否全部读出标记位 }FAT_TABLE; 上面的结构体利用两个数组Fat_Base_Tab和Fat_Base_Len分别存放FAT表的基址和这个基址所管辖的长度.比如,一首歌曲如果从首簇到最后一个簇都是连续的,那么我用一个u32的字节和一个u16的字节就可以表示整个歌曲的FAT表了(歌曲不能大于65536个簇),Fat_Table_Size 表示的一个小FATtinyTab所包含的不连续簇的个数,这里设置为10个.也就是一个tinyFAT最多可以提供十个基址.但是我们的歌曲可能不止10个不连续的簇(事实上我现在碰到基本都是一个基址就够了),这样我可以重新开辟一个新的tinyFAT,来满足多基址的需求,在开辟新的tinyFAT的时候,把先前的tinyFAT头保存在Fat_Base_Head里面,这是为了方便向上查找.然后从最后一个cluster开始,COPY余下的FAT到tinyFAT,直到整个文件COPY完,此时置位Fat_Over.表示整个文件的FAT copy 完了.这样对于任意大小的文件,我都可以向下查找.但是向上查找只限于Fat_Table_Size*Fat_Head_Size 个不同基址的范围.这里是100.对一般应用,这已经是足够了的. 贴上现在在用的代码.已经移植到VS1053的MP3上,后续补充测试结果.现在正常播放没问题.证明前向访问是没有问题的. 个人一时头脑发热,难免有误,望各位网友指正. //cluster:文件的首簇 //将FAT表,从头到尾COPY过来,如果没COPY完,则Fat_Over=0,否则为1 //发烧友@HYW //091119 void Copy_Fat_Table(unsigned long cluster) { u32 bcluster; u8 fat_base;//0~Fat_Table_Size FAT_TAB.Fat_Over=0; for(fat_base=0;fat_base FAT_TAB.Fat_Base_Tab[fat_base]=0; FAT_TAB.Fat_Base_Len[fat_base]=0;//全部清空 } fat_base=0; bcluster=cluster;//起始簇,不能丢失的. FAT_TAB.Fat_Base_Tab[fat_base]=bcluster; FAT_TAB.Fat_Base_Len[fat_base]=1;//有1个数据了,就是最新的bcluster while(1) { bcluster=FAT_NextCluster(bcluster); if((FAT32_Enable==0&&bcluster==0xffff)||bcluster==0x0ffffff8||bcluster==0x0fffffff)//文件结束 { FAT_TAB.Fat_Over=1;//文件COPY结束 break; } if(bcluster-FAT_TAB.Fat_Base_Tab[fat_base]-FAT_TAB.Fat_Base_Len[fat_base]!=0)//是否满足偏移条件 { fat_base++;//启用下一个BASE if(fat_base>=Fat_Table_Size)//超出了缓冲区范围,文件太大了/磁盘太零散了!!! { FAT_TAB.Fat_Over=0;//文件COPY结束 break; } FAT_TAB.Fat_Base_Tab[fat_base]=bcluster; FAT_TAB.Fat_Base_Len[fat_base]=1;//有1个数据了,就是最新的bcluster }else FAT_TAB.Fat_Base_Len[fat_base]++;//基址偏移量增加 } //监控用 printf("Fat_Over:%dn",FAT_TAB.Fat_Over); printf("Fat_Head_Pos:%dn",FAT_TAB.Fat_Head_Pos); printf("Fat_Base_Tab[0]:%dn",FAT_TAB.Fat_Base_Tab[0]); printf("Fat_Base_Tab[1]:%dn",FAT_TAB.Fat_Base_Tab[1]); printf("Fat_Base_Tab[2]:%dn",FAT_TAB.Fat_Base_Tab[2]); } //得到cluster的上一个簇号 //发烧友@HYW //091119 u32 FatTab_Prev_Cluster(unsigned long cluster) { u8 t; u32 tempclust; RSTP: for(t=0;t if(cluster><=(FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)&&cluster>=FAT_TAB.Fat_Base_Tab[t])break;//在这个BASE内 } if(cluster==FAT_TAB.Fat_Base_Tab[t])//是在BASE,但是是第一个 { if(t==0)//这份FAT表 全部找完还没找到 { if(FAT_TAB.Fat_Head_Pos>0)//不超过范围 { FAT_TAB.Fat_Head_Pos--; tempclust=FAT_TAB.Fat_Base_Head[FAT_TAB.Fat_Head_Pos];//拷贝上一个tinyFAT表的表头 }else return cluster; //无法继续向上 Copy_Fat_Table(tempclust);//COPY 上一个tinyFAT表 goto RSTP; //return FAT_TAB.Fat_Base_Tab[Fat_Table_Size-1]+FAT_TAB.Fat_Base_Len[Fat_Table_Size-1]-1;//返回上一个簇号 } return FAT_TAB.Fat_Base_Tab[t-1]+FAT_TAB.Fat_Base_Len[t-1]-1;//上一个簇号 }else return --cluster;//返回上一个簇 } //得到cluster的下一个簇号 //发烧友@HYW //091119 u32 FatTab_Next_Cluster(unsigned long cluster) { u8 t; RESN: for(t=0;t if(cluster><=(FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)&&cluster>=FAT_TAB.Fat_Base_Tab[t])break;//在这个BASE内 } if(cluster==FAT_TAB.Fat_Base_Tab[t]+FAT_TAB.Fat_Base_Len[t]-1)//是在BASE,但是是最后一个了 { if((t+1)==Fat_Table_Size)//全部找完还没找到 { if(FAT_TAB.Fat_Over)return 0x0ffffff8;//文件结束了 if(FAT_TAB.Fat_Head_Pos FAT_TAB.Fat_Base_Head[FAT_TAB.Fat_Head_Pos]=FAT_TAB.Fat_Base_Tab[0];//拷贝当前tinyFAT表的第一个簇 FAT_TAB.Fat_Head_Pos++; } Copy_Fat_Table(cluster);//COPY 余下的FAT表 goto RESN; } if(FAT_TAB.Fat_Base_Len[t+1]==0)return 0x0ffffff8;//没有后续簇了 return FAT_TAB.Fat_Base_Tab[t+1];//下一个簇号 }else return ++cluster;//返回下一个簇 } //读下一簇簇号 //Return the cluster number of next cluster of file //Suitable for system which has limited RAM unsigned long FAT_NextCluster(unsigned long cluster) { DWORD sector; DWORD offset; if(FAT32_Enable)offset = cluster/128;//FAT32的FAT表中,用四个字节表示一个簇地址.512/4=128 else offset = cluster/256; //FAT16的FAT表中,用两个字节表示一个簇地址.512/2=256 if(cluster><2)return 0x0ffffff8; //簇0,1不能用于存放 sector=FirstFATSector+offset;//计算该簇实际所在扇区 if(SD_ReadSingleBlock(sector,fat_buffer))return 0x0ffffff8;//读取FAT表,发生错误是返回0x0ffffff8 if(FAT32_Enable) { offset=cluster%128;//计算在扇区内的偏移 sector=((unsigned long *)fat_buffer)[offset];//u32 } else { offset=cluster%256;//计算在扇区内的偏移 sector=((unsigned short *)fat_buffer)[offset];//u16 } return (unsigned long)sector;//return the cluste number } |
|
|
|
原子,我看了你上边的文字部分,如果说每一个簇的下一个比上一个大一,确实可以这样做,而且一般初始化的时候也确实如此,但是要是删除某一首歌曲后,或者删除很多后,这个方法貌似不可以了吧?因为链接的簇开始利用碎片存储了。你觉得我说的有道理吗?还是说我没有明白你的思想。指点下。
|
|
|
|
只要碎片不多,基本就没问题的.我里面做了很多个base来记录有碎片后的情况.如果无任何碎片,我一个base就搞完了的.
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1845 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1647 浏览 1 评论
1116 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
745 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1700 浏览 2 评论
1959浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
766浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
595浏览 3评论
618浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
578浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-4 10:59 , Processed in 0.860031 second(s), Total 82, Slave 66 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号