搜索
bottom↓
回复: 79

[原创]开放源代码(FAT16文件系统)

[复制链接]

出0入0汤圆

发表于 2005-12-5 15:26:40 | 显示全部楼层 |阅读模式
这个源代码是我在没有参考任何现成的代码的情况下一个字母一个字母敲进去的.目前实现了创建文件,读写文件的操作,暂时不支持子目录、长文件名、文件删除、重命名等操作。



在开发时用的是Visual Studio 2005 和一个虚拟硬盘软件:WinDiskXP,在WindowsXP上测试是成功的。但是没有在AVR的硬件上测试过,只在AtmanAVR上编译过。在Visual Studio 2005上为了保证字节对齐用了#pargma pack(1)语句在Atman上编译时有警告不过不晓得对结果有没有影响。



这是在AtmanAVR5上编译的结果:



Generating Code...

Program memory usage: 1776 bytes, 2.71% full.

Global variables usage: 528 bytes



528个比特的全局变量中包含了512个比特的缓冲区。本来是给访问SD卡准备的,但是SD卡驱动还没有做好,所以留了读取一个扇区到缓冲区和从缓冲区写到一个扇区两个函数没有完成。使用是先用ReadBPB读取BPB结构,然后就可以操作文件了。注意文件名是一个11字节长的字符串,前8个是文件名,后3个是扩展名。

有SD卡驱动的帮忙测试一下看能不能正常访问SD卡。



代码:点击此处下载armok0190787.rar




-----此内容被linhaimi于2005-12-07,14:38:00编辑过

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2005-12-5 19:13:01 | 显示全部楼层
掌声

出0入0汤圆

发表于 2005-12-5 22:55:12 | 显示全部楼层
谢谢,什么时候大虾把FAT32的也高个范例出来??

出0入0汤圆

发表于 2005-12-6 08:29:12 | 显示全部楼层
NB,才2k不到

出0入0汤圆

发表于 2005-12-7 00:10:23 | 显示全部楼层
粗略看了一下,没有针对Flash媒质有特殊处理的地方。原程序中对扇区的“ 读-改写-回写 ”操作在Flash上不能实现,因为Flash必须先擦除才可以改写。!!(最小操作单位为一个Sector,最小擦除单位为一个Block(16k?))



完整的FAT的实现的参考代码很多,为什么不参考一下呢?起码不用费精力去重做人家已经做得很好的地方了。



因为FAT的原设计是在磁盘媒质上实现的,可以随机读写。可是Flash媒质最麻烦的在于:不可以随机写/改写,算法中必须绕开这个问题。

所以,我们能看到的最多的就是读SD卡(做MP3),而要实现文件系统的‘写’就很麻烦。起码RAM要足够。



我也没实现过,但是这方面看的资料比较多,上面这个结论应该没有错。

而且,FAT的版权好像微软没有放弃哦。






-----此内容被mig29于2005-12-07,00:48:34编辑过

出0入0汤圆

发表于 2005-12-7 01:03:55 | 显示全部楼层
如果RAM够的话,可以把 FAT表 和 DIR区 缓冲出来,必要的时候才回写,实现一个轻量的文件系统还是可以的,



在只有1K RAM的情况下,难度大大增加。如果使用Flash的某个Block做缓冲,那么要实现扇区均衡算法,因为Flash的寿命也只有10万次。极端情况的应用是:实时写文件!这种情况下,除了在RAM中缓冲 FAT表 和 DIR区,别无选择。

出0入0汤圆

 楼主| 发表于 2005-12-7 12:36:48 | 显示全部楼层
我在写这个代码的时候还没有办法访问SD卡之类的Flash介质,于是就用读、写扇区的两个函数把介质访问的过程抽象了,专心写有关FAT的代码。关于Flash的Block的问题是想在SD卡或Flash芯片驱动中解决,如果RAM足够的话我会在Flash介质的驱动去做缓冲的。

还有就是写这个代码的主要目的是从Flash介质中读数据,写文件的代码都是后来加的,如果是只读数据的话应该没有什么问题的。
-----此内容被linhaimi于2005-12-07,12:49:54编辑过

出0入0汤圆

发表于 2006-2-24 16:06:47 | 显示全部楼层
请教搂主,一下这段程序,我看得不是很明白,

uint16 ReadFAT(uint16 Index)

//********************************************************************************************

{

        uint16 *RAM = (uint16*)BUFFER;

        ReadBlock(BPB_RsvdSecCnt + Index / 256);//

        return RAM[Index % 256];

}



为什么返回值是一个16位长的字,这里并不是一个完整的文件链表

还有INDEX表示什么意思?

出0入0汤圆

发表于 2006-2-24 16:23:01 | 显示全部楼层
下载,收藏,学习。

出0入0汤圆

 楼主| 发表于 2006-2-24 17:46:16 | 显示全部楼层
这个函数是读取文件分配表的第Index项的记录。

文件分配表每一条记录是16位的。所以用一个uin16的指针指向缓冲区,方便以后读取。

缓冲区只有512Byte(256个uint16),不可能全部装下FAT。以512byte为一块,只读取需要的块到缓冲区。然后用之前指向缓冲区的uint16指针读取即可。

出0入0汤圆

发表于 2006-2-24 18:04:10 | 显示全部楼层
那就麻烦楼主帮我看看我的FAT读写思路是否正确?





http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=588848&bbs_page_no=1&bbs_id=1000

出0入0汤圆

 楼主| 发表于 2006-2-24 20:09:39 | 显示全部楼层
我觉得是正确的,目录项里面的起始簇号就是它在FAT表中的位置,有了文件长度且FAT表没有问题的话,可以不用管结尾的FFFF.

出0入0汤圆

发表于 2006-2-26 15:22:12 | 显示全部楼层
请问楼主的

OperateFile(uint8 Write ,uint8* Name, uint32 Start, uint32 Length, void* Data)

函数里面,Start是什么意思?是数据区开始的扇区号?还是具体的地址,还是簇号?

出0入0汤圆

 楼主| 发表于 2006-2-26 15:52:00 | 显示全部楼层
文件开头的偏移地址

如:

从文件的Start地方读取Length个Byte到Data中.

出0入0汤圆

发表于 2006-2-26 22:10:47 | 显示全部楼层
哦,真是谢谢楼主,留个MSN吧,大家交流一下。

出0入0汤圆

发表于 2006-5-20 18:04:38 | 显示全部楼层
那里可以下载VMLAB

3.10

出0入0汤圆

发表于 2006-6-4 16:10:11 | 显示全部楼层
请问楼主的

OperateFile(uint8 Write ,uint8* Name, uint32 Start, uint32 Length, void* Data)

函数里面,Start是什么意思?是数据区开始的扇区号?还是具体的地址,还是簇号?  

   

文件开头的偏移地址

如:

从文件的Start地方读取Length个Byte到Data中.





楼主,start的具体地址怎么获得

程序里面你总不能自己给他赋值吧

出0入0汤圆

发表于 2006-6-5 09:28:13 | 显示全部楼层
顶一下!

出0入0汤圆

发表于 2006-8-7 09:47:44 | 显示全部楼层
请问 ,SD的系统文件是在什么环境下编写、运行的??



刚刚接触,想玩玩,恳望赐教!



谢谢先^_^

出0入0汤圆

 楼主| 发表于 2006-8-7 09:55:35 | 显示全部楼层
需要:

Visual Studio 2005

ATMainAVR

WinHEX

SD卡读卡器

SD卡一张

出0入0汤圆

发表于 2006-8-7 10:11:33 | 显示全部楼层
噢,万分感激楼主



可否把这些东东发给我?最好可以有一些相关资料^_^



我的邮箱:s_yhzhuang@stu.edu.cn

出0入0汤圆

 楼主| 发表于 2006-8-7 15:44:25 | 显示全部楼层
算了吧,一个 VisualStudio2005就将近4GB

多在网上搜索下吧,比如骡子

出0入0汤圆

发表于 2007-1-29 14:33:08 | 显示全部楼层
lz 的图片很有意思...

哈哈哈哈哈哈

出0入0汤圆

发表于 2007-4-11 14:57:12 | 显示全部楼层
顶楼主,,在楼主的fat16的文件系统基础下,,,写了个sd卡的fat32的,,

1》   能够创建空文件了,,(xxx.txt)文件名注意要大写字母,,

因为fat32对文件名有转换小写变大写,,我刚开始不知道,,创建文件就是在winxp

下读不出,,用winhex可以看到,,,

2》 能够向自己创建的文件写数据,,现只能写1个扇区的数据,,(<512byte)

有空,再把它写完整,, 或者要用到时再写完整,,   

3》 楼主的c学得太牛了,,向他学习了,,,

严重支持楼主,, 同时谢谢公开sd驱动的人,,

出0入0汤圆

发表于 2007-4-11 15:01:41 | 显示全部楼层
#define file_delete    0xE5



#define BPB_addr      32   

#define dir_begin_clusId     2

//=============================

//you can not use little a,b you must use AB,or they consider it  use the same name

uint8 buf[512] ;

uint16 BPB_BytesPerSec;

uint8  BPB_SecPerClus;

uint16 BPB_RsvdSecCnt;

uint8  BPB_NumFATs;   

uint32 BPB_TotSec32;

uint32 BPB_FATsize;

uint32 BPB_HiddSec;

uint32 fat1_addr;

uint32 fat2_addr;

//=====================

uint8 file_clus_sec;

uint8 file_clus_sec_num;

//============================

typedef struct

{

        uint8 BS_jmpBoot[3];

        uint8 BS_OEMName[8];

       

        uint16 BPB_BytesPerSec;

        uint8 BPB_SecPerClus;

       

        uint16 BPB_RsvdSecCnt;

        uint8 BPB_NumFATs;

       

        uint16 BPB_4null;

        uint16 BPB_5null;

       

        uint8 BPB_Media;

        uint16 BPB_3null;

       

        uint16 BPB_SecPerTrk;

        uint16 BPB_NumHeads;

       

        uint32 BPB_HiddSec;

        uint32 BPB_TotSec32;

       

        uint32 BPB_FATsize;

        uint16 BS_null;

       

        uint16 BPB_FATversion;

        uint32 BPB_begin_clus;

       

        uint16 BS_FilSysinfor;

        uint16 BS_bootbk;

       

        uint8  BS_resnull[12];

        uint8  BS_drivnum;

       

        uint8  BS_2null;

        uint8  BS_Extendid;

       

        uint8  BS_serial_num[4];

        uint8  BS_partion_name[11];

       

        uint8  BS_FAT_name[8];

       

        uint8  ExecutableCode[420];

        uint8 ExecutableMarker[2];

} FAT_BPB;

typedef struct

{

        uint8 NAME[8];

        uint8 TYPE[3];

} FILE_NAME;



typedef struct

{

        FILE_NAME FileName;

        uint8 FileAttrib;

        uint8 UnUsed[8];

        uint16 File_Start_H;

        uint16 FileUpdateData[2];

        uint16 File_Start_L;

        uint32 Size;

} DIR;

typedef struct

{

        uint16 ClusID;

        uint16 SecOfClus;

        uint16 ByteOfSec;

} DATA_POSIT;







//********************************************************************************************

//读一个扇区

uint8 ReadBlock(uint32 LBA)

//********************************************************************************************

{

return        SD_Read_Single_Block(LBA,  buf);

}



//********************************************************************************************

//写一个扇区

uint8 WriteBlock(uint32 LBA)

//********************************************************************************************

{

return SD_Write_Single_Block(LBA,  buf);

}



//*****************************************



//********************************************************************************************

//读取BPB数据结构

void ReadBPB(void)

//********************************************************************************************

{

        FAT_BPB* BPB = (FAT_BPB*)buf;

       

    ReadBlock(BPB_addr);

        //获取参数

        BPB_BytesPerSec = BPB->BPB_BytesPerSec;

        BPB_SecPerClus = BPB->BPB_SecPerClus;

        BPB_RsvdSecCnt = BPB->BPB_RsvdSecCnt;

        BPB_NumFATs=BPB->BPB_NumFATs; //how many fats  ==2

       

        BPB_TotSec32 = BPB->BPB_TotSec32;

        BPB_FATsize = BPB->BPB_FATsize;

        BPB_HiddSec = BPB->BPB_HiddSec;

    fat1_addr=BPB_addr+BPB_RsvdSecCnt;

        fat2_addr=BPB_addr+BPB_RsvdSecCnt+BPB_FATsize;

}

//==============

//获取根目录开始扇区号

uint32 DirStartSec(void)

//***********************************************************

{

        return BPB_addr+BPB_RsvdSecCnt + BPB_FATsize * BPB_NumFATs;//32+38+973*2=2016

}



//**********************************************************



//*******************************************************************************

//获取一个簇的开始扇区

uint32 Clus2LBA(uint32 ClusID)

//****************************************************************

{

        return DirStartSec() + BPB_SecPerClus * (ClusID - 2);

}



//**************************************************************



void EmptyBytes(void* D, uint32 size)

//********************************************************************************************

{

        uint32 i;

        uint8* data = (uint8*)D;

        for(i = 0; i < size; i++)

        {

                *data++ = 0;

        }

}



//******************************************************************

//********************************************************************************************

uint8 IsEqual(void* A, void* B, uint8 Size)

//********************************************************************************************

{

        uint8 i, *a = A, *b = B;

        for(i = 0; i < Size; i++)

                if(a != b)

                        return 0;

        return 1;

}

//***********************************************************

void CopyBytes(void* S, void* D, uint32 size)

//********************************************************************************************

{

        uint8 *s = S, *d = D;

        uint32 i;

        for(i = 0; i < size; i++)

                *d++ = *s++;

}



//*******************************************

//写文件分配表的指定项

void WriteFAT(uint32 Index, uint32 Value)

//********************************************************************************************

{

        uint32 *RAM = (uint32*)buf;

        uint32 SecID;

        SecID = fat1_addr + Index / 128;

        ReadBlock(SecID);

        RAM[Index % 128] = Value;

       

        WriteBlock(SecID);

        SecID = fat2_addr + Index / 128;

        WriteBlock(SecID);

}

//*******************************

//写根目录的指定项

void WriteDIR(uint16 Index, DIR* Value)

//********************************************************************************************

{

        uint32 LBA =Clus2LBA(Index)+file_clus_sec;

        ReadBlock(LBA);

        CopyBytes(Value, &buf[file_clus_sec_num * 32], 32);

        WriteBlock(LBA);

}



//读取文件分配表的指定项

uint32 ReadFAT(uint32 Index)

//********************************************************************************************

{

        uint32 *RAM = (uint32*)buf;//init piont address

        ReadBlock(fat1_addr + Index /128);

        return RAM[Index % 128];

}

//*************************************************

void clr_this_clus(uint32 index)//簇号

{

uint8 i;

for(i = 0; i < BPB_SecPerClus; i++)

        {

        EmptyBytes(buf,512);

        WriteBlock(Clus2LBA(index)+i);//清空一个簇

       

        }



}



//获取一个空的FAT项,只要有空间就可以获得



uint32 Get_blank_FATid(void)

//********************************************************************************************

{   uint16 j;

        uint32 FAT_Count, i;

        uint32 *RAM = (uint32*)buf;

        FAT_Count =BPB_FATsize ; //FAT表总项数

        for(i = 0; i < FAT_Count; i++)

        {  ReadBlock(fat1_addr + i);

            for(j=0;j<128;j++)

                if(RAM[j] == 0)

                        return i*128+j;

        }

        return 0;

}





//获取根目录中可以使用的一项

//可以向目录中加入新的簇链,,这样只要有磁盘空间就总可以找到目录

uint32 GetEmptyDIR(void)

//*********************************************************

{

        uint32  Dir_index,dir_fat_num,next_fat_index;

        uint8 i,m;

        dir_fat_num=dir_begin_clusId;//2

       

        Dir_index= Clus2LBA(dir_fat_num);//2016

next_dir0_clus:        for(i = 0; i < BPB_SecPerClus; i++)

        {

                ReadBlock(Dir_index + i);

                for(m = 0; m <16; m++)

                {

                        if((buf[m * 32] == 0) )//|| (buf[m * 32] == 0xe5))

                        {   file_clus_sec=i;

                                file_clus_sec_num=m;

                                return  dir_fat_num; //找到对应的目录项,返回其簇号

                        }

                }

        }

        next_fat_index=ReadFAT(dir_fat_num);//read next fat num,,or no

        if(next_fat_index==0x0fffffff)     //you must creat a new fat address to save your new dir

       {

           next_fat_index=Get_blank_FATid();

          

           clr_this_clus(next_fat_index);//

           WriteFAT(dir_fat_num,next_fat_index);// write_old_fat_index

           WriteFAT(next_fat_index,0x0fffffff);// write_new_fat_index

          

           Dir_index = Clus2LBA(next_fat_index); goto next_dir0_clus ;

           }

       

        else {dir_fat_num=next_fat_index;Dir_index = Clus2LBA(dir_fat_num);

              goto next_dir0_clus ; }

       

}

//********************************************************************









//获得和文件名对应的目录项的簇号

uint32 Get_Same_FileID(uint8 * Name)

//********************************************************************************************

{

        uint32  Dir_index,dir_fat_num;

        uint8 i,m;

        dir_fat_num=dir_begin_clusId;//2

       

        Dir_index= Clus2LBA(dir_fat_num);//2016

next_dir_clus:        for(i = 0; i < BPB_SecPerClus; i++)

        {

                ReadBlock(Dir_index + i);

                for(m = 0; m <16; m++)

                {   if(buf[m * 32]==0) return 0xffffffff;//end and you donot find it

                        if(IsEqual(Name, &((DIR*)&buf[m * 32])->FileName, 11))

                        {

                                //H= ((DIR*)&buf[m * 32])->File_Start_H;

                                //L= ((DIR*)&buf[m * 32])->File_Start_L;

                                file_clus_sec=i;

                                file_clus_sec_num=m;

                                return  dir_fat_num; //找到对应的目录项,返回其簇号

                        }

                }

        }

        dir_fat_num=ReadFAT(dir_fat_num);//read next fat num,,or no

        if(dir_fat_num==0x0fffffff)   return 0xffffffff;//没有找到对应的目录项,返回ffffffff

        else {Dir_index = Clus2LBA(dir_fat_num); goto next_dir_clus ; }

       

}

//*****************************************************************       

//创建一个空文件       

uint8 CreateFile(uint8* FileName)

//********************************************************************************************

{

        //uint32  Fat_Id;

        uint32  Dir_id;

        uint8 Creat_time[8]   = {0x18,0x14,0x58,0xb5,0x88,0x36,0x89,0x36};

        DIR FileDir;

   

        if(Get_Same_FileID(FileName)!=0xffffffff)  return 1;//有了这个文件了,,你不能

    CopyBytes(FileName, &FileDir.FileName, 11);

        FileDir.FileAttrib=0x20;

        CopyBytes(Creat_time, &FileDir.UnUsed, 8);

        //Fat_Id=Get_blank_FATid();   //获得一个空白的fat cluster num

        FileDir.File_Start_H=0;

        FileDir.File_Start_L=0;

    FileDir.Size=0;   

        //生成一个文件结构



       

        Dir_id=GetEmptyDIR();           //获得一个空白的目录

       

        //get_hex(Dir_id/256);get_hex(Dir_id%256);

    WriteDIR(Dir_id,&FileDir);  

       

        //WriteFAT(Fat_Id, 0x0fffffff);   //写入fat表同时写好2个fat表

        //get_hex(Fat_Id/256);get_hex(Fat_Id%256);

   return 0;



}



uint8  WriteFile(uint8* FileName,uint8 *data,uint32 size)

{

//uint32  Dir_index;

    uint32  dir_fat_num,H,L;

        uint32  file_size ;

        uint32  Fat_Id;

    //DIR FileDir;

       

        dir_fat_num=Get_Same_FileID(FileName);  //获得其目录簇号

    if(dir_fat_num==0xffffffff) return   1;//没有找到该文件

        ReadBlock(Clus2LBA(dir_fat_num)+file_clus_sec);

        file_size=((DIR*)&buf[file_clus_sec_num * 32])->Size;//获得其长度

       

        //============================================================

        if(file_size==0)  

        {Fat_Id=Get_blank_FATid();   //获得一个空白的fat cluster num

         H=Fat_Id/65536;//(uint16)Fat_Id>>16;

         L=Fat_Id%65536;//(uint16)Fat_Id&0x0000ffff;

         ReadBlock(Clus2LBA(dir_fat_num)+file_clus_sec);

        ((DIR*)&buf[file_clus_sec_num * 32])->File_Start_H=H;

    ((DIR*)&buf[file_clus_sec_num * 32])->File_Start_L=L;

        ((DIR*)&buf[file_clus_sec_num * 32])->Size=size;

         

         WriteBlock(Clus2LBA(dir_fat_num)+file_clus_sec);

         WriteFAT(Fat_Id, 0x0fffffff);   //写入fat表同时写好2个fat表

         ReadBlock(Clus2LBA(dir_fat_num)+file_clus_sec);

        }

       

         H= ((DIR*)&buf[file_clus_sec_num * 32])->File_Start_H;

         L= ((DIR*)&buf[file_clus_sec_num * 32])->File_Start_L;

        dir_fat_num=(H*65536+L);  //获得其簇号

   

   

    EmptyBytes(buf,512);//清空一个扇区的数据

    CopyBytes(&data[0], &buf[0], size);

       

        WriteBlock(Clus2LBA(dir_fat_num));//现在只能写一个扇区

return 0;       

}



//=======================================



uint8 ReadFile(uint8* FileName)

{

        uint32  Dir_index,dir_fat_num,H,L;

        uint32  r_file_size ;

        uint16   j;

        uint8 i;

        dir_fat_num=Get_Same_FileID(FileName);  //获得其目录簇号

    if(dir_fat_num==0xffffffff) return   1;//没有找到该文件

        ReadBlock(Clus2LBA(dir_fat_num)+file_clus_sec);

        r_file_size=((DIR*)&buf[file_clus_sec_num * 32])->Size;//获得其长度

         H= ((DIR*)&buf[file_clus_sec_num * 32])->File_Start_H;

         L= ((DIR*)&buf[file_clus_sec_num * 32])->File_Start_L;

        dir_fat_num=(H*65536+L);

   

Dir_index= Clus2LBA(dir_fat_num);//获得文件第一个数据簇

next_file_clus:        for(i = 0; i<BPB_SecPerClus; i++)

        {

                ReadBlock(Dir_index +i);

        for(j=0;j<512;j++)

                {w_dat(buf[j]); _delay_ms(1);if((r_file_size--)==0) return 0; }

               



        }

        dir_fat_num=ReadFAT(dir_fat_num);//read next fat num,,or no

        if(dir_fat_num==0x0fffffff)   return   0;

        else {Dir_index = Clus2LBA(dir_fat_num); goto next_file_clus ; }

       

}

出0入0汤圆

发表于 2007-4-11 15:10:20 | 显示全部楼层
i=CreateFile(file_pcj2);

get_hex(i);

display_string("crf2");

i=CreateFile(file_pcj);

get_hex(i);

display_string("wtf");

i=WriteFile(file_pcj,hehe,sizeof(hehe));

get_hex(i);

display_string("rf");

i=ReadFile(file_pcj);





出0入0汤圆

发表于 2007-5-22 10:56:39 | 显示全部楼层
请问,读写的速度如何?创建文件需要多长时间?

出0入0汤圆

发表于 2007-7-4 10:40:40 | 显示全部楼层
非常感谢!

出0入0汤圆

发表于 2007-7-9 11:34:54 | 显示全部楼层
LZ可以留个联系方式吗

出0入0汤圆

发表于 2007-9-1 16:39:08 | 显示全部楼层
请问pcj203 :

//********************************************************************************************

//读取BPB数据结构

void ReadBPB(void)

//********************************************************************************************

{

FAT_BPB* BPB = (FAT_BPB*)buf;



ReadBlock(BPB_addr);

//获取参数

BPB_BytesPerSec = BPB->BPB_BytesPerSec;

BPB_SecPerClus = BPB->BPB_SecPerClus;

BPB_RsvdSecCnt = BPB->BPB_RsvdSecCnt;

BPB_NumFATs=BPB->BPB_NumFATs; //how many fats ==2



BPB_TotSec32 = BPB->BPB_TotSec32;

BPB_FATsize = BPB->BPB_FATsize;

BPB_HiddSec = BPB->BPB_HiddSec;

fat1_addr=BPB_addr+BPB_RsvdSecCnt;

fat2_addr=BPB_addr+BPB_RsvdSecCnt+BPB_FATsize;

}

在读取BPB:ReadBlock(BPB_addr);前为什么不读MBR以得到DPT的首扇区的相对扇区号

还有按 linhaimi 方法ReadBlock(0);读出的好像总是MBR,就没有出现BPB,想问这里面有什么不同吗,

我用ReadBlock(0);读出我的SD卡得:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 03 37 00 06 03 C3 E6 F3 00 00 00 0D B3 1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA

我感觉有点不对,但不知为什么,还有在80 03 37 00 06 03 C3 E6 F3 00 00 00 0D B3 1E 00 中按说应该是DPT,第5个06查了说是BIGDOS系统类型,它与FAT16有什么区别吗,期待答案中谢谢

出0入0汤圆

发表于 2007-9-1 16:43:53 | 显示全部楼层
由于没有读卡器也没法用WINHIX看内部,现在读BPB一直有问题

出0入0汤圆

发表于 2007-9-1 23:48:34 | 显示全部楼层
to: CSLIN93 玩耍人生

对sd卡,读到第2个55 AA才是BPB,第1个是不对的.即需要一个查找过程.

出0入0汤圆

发表于 2007-9-3 07:42:37 | 显示全部楼层
牛人啊

出0入0汤圆

发表于 2007-9-3 08:07:25 | 显示全部楼层
tks!

出0入0汤圆

发表于 2007-9-4 14:10:59 | 显示全部楼层
哈,BPB已经读出,就是80 03 37 00 06 03 C3 E6 F3 00 00 00 0D B3 1E 00 中偏移F3 00 00 00 (实际为0x000000F3),但是我现有个问题就是在存储器中大于2字节的数为倒过来放置,而我用结构体

//BPB structures

struct BootSec

{

        unsigned char  BS_jmpBoot[3];

        char           BS_OEMName[8];

        unsigned int   BPB_BytesPerSec; //2 bytes

        unsigned char  BPB_SecPerClus;

        unsigned int   BPB_RsvdSecCnt; //2 bytes

        unsigned char  BPB_NumFATs;

        unsigned int   BPB_RootEntCnt; //2 bytes

        unsigned int   BPB_TotSec16; //2 bytes

        unsigned char  BPB_Media;

        unsigned int   BPB_FATSz16; //2 bytes

        unsigned int   BPB_SecPerTrk; //2 bytes每道扇区数(Sectors Per Trark)

        unsigned int   BPB_NumHeads; //2 bytes

        unsigned long  BPB_HiddSec; //4 bytes

        unsigned long  BPB_TotSec32; //4 bytes

};

读的时候没有得出我要的值即读出的也是反倒的数在偏移时当然是错的,我按BPB上的值倒反后直接手工赋值结构体内的值得到了正确的偏移,我想问的是难道这个也得人工转换后才能用吗,有什么好方法大家喷喷

出0入0汤圆

发表于 2007-9-4 19:09:00 | 显示全部楼层
怎么没人回呀,我查了查这就是传说中的big_endian vs little_endian谈到字节序的问题,牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。

little endian方式的CPU要传给big endian方式CPU一个字节的话,其本身在传输之前会在本地就读出这个8比特的数,然后再按照网络字节序的顺序来传输这8个比特,这样的话到了接收端不会出现任何问题。而假如要传输一个32比特的数的话,由于这个数在littel endian方存储时占了4个字节,而网络传输是以字节为单位进行的,little endian方的CPU读出第一个字节后发送,实际上这个字节是原数的LSB,到了接收方反倒成了MSB从而发生混乱.难道这个还真的要人工转换吗,怎么在所有的SD例子中没一个提到这个问题,还是我理解错误,或是有什么好的方法来识别

出0入0汤圆

发表于 2007-9-10 10:38:23 | 显示全部楼层
哈,没人跟进呀,不过问题都解决了,现在能实现文件创建、读写(大小不限)、删除、查文件名、在已有文件内加内容等,不过还想继续深入想再实现新卡的格式化功能(还在资料摸索中),还有在上贴中大端和小端存储的问题上我是用SD卡回来的地址数据进行反换后再用CPU读取数据,而写地址时也是实际值反换后再存入SD卡,不换的话会出现数据没法读取的情况,
//32byte的数据倒反
U32 turnover32byte(U32  parameter)
{
   U32 buf[3];
   buf[0]=(parameter&0x000000ff)<<24;
   buf[1]=(parameter&0x0000ff00)<<8;
   buf[2]=(parameter&0x00ff0000)>>8;
   parameter=((parameter&0xff000000)>>24)+buf[0]+buf[1]+buf[2];
   return parameter;
}
//16byte的数据倒反
U16 turnover16byte(U16 parameter)
{
   U16  buf;
   buf=(parameter&0x00ff)<<8;
   parameter=(parameter>>8)+buf;
   return parameter;
}

出0入0汤圆

发表于 2007-9-12 14:01:23 | 显示全部楼层
支持一下,打算做CF卡读写,应该用得着吧。

出0入0汤圆

发表于 2007-9-12 19:24:39 | 显示全部楼层
现在好多SD/MMC卡的例子都是驱动或FAT文件,实现格式化的功能好像没见过呀,哈,啃了几天的数据资料做了N次的实验,错写了N次MBR和DBR,不过还是成功出炉了,整理完后会再开个贴,咱也弄个"原创"玩玩.

出0入0汤圆

发表于 2007-9-14 11:37:22 | 显示全部楼层
ReadBlock(BPB_addr) 为什么 BPB_ addr  是32?不明白了 BPB不是在第一个扇区的嘛?

出0入0汤圆

发表于 2007-9-14 18:21:47 | 显示全部楼层
回复:cocacolahj
他这个写了个固定的偏移BPB_ addr =32是针对他的SD卡写,不同的卡BPB的偏移地址是不同的,BPB偏移值在用ReadBlock(0) 读出MBR后如:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 03 37 00 06 03 C3 E6 F3 00 00 00 0D B3 1E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA  在DPT:80 03 37 00 06 03 C3 E6 F3 00 00 00 0D B3 1E 00 中的F3 00 00 00 就是BPB的偏移地址(注意:用单片机读时把F3 00 00 00 反转后即0x000000F3)再执行ReadBlock(0x000000F3);得出的512字节就是真正的DBR,而BPB就在DBR中,得出BPB后就可以进行其它运算了

出0入0汤圆

发表于 2007-9-18 11:42:39 | 显示全部楼层
to  玩耍人生  谢谢!@ 我看了FAT文件系统的资料 但是他所说的MBR是在针对硬盘的,请问,是不是SD卡和硬盘是类似的阿

出0入0汤圆

发表于 2007-9-19 16:44:50 | 显示全部楼层
哈,其实SD卡也是一个小形的硬盘,一样有MBR、DBR、FAT1、FAT2、DIR(根目录)、DATA,你看FAT文件系统也是完全符合SD卡的,有的人用查询的方法找到BPB(即找第二个55AA),其实在FAT16文件中是对的,但在FAT32中却不一样(我是用实验得出的结果),所以用MBR中的偏移地址找DBR是一定能找到BPB的,还有就是在格式化时MBR中的DPT:80 03 37 00 06 03 C3 E6 F3 00 00 00 0D B3 1E 00 除了选的系统类型(BIGDOS:06、FAT16:04,FAT32:0B)不同也改变外其它都不变,注意在写入数据做实验时千万不要用地址0即WriteBlock(0); 否则你得用手工一个个写MBR(哈,我用手工写了N次MBR了)

出0入0汤圆

发表于 2007-9-28 21:00:55 | 显示全部楼层

C语言写的太好了

出0入0汤圆

发表于 2007-9-28 21:46:28 | 显示全部楼层
不顶
就对不起党中央

出0入0汤圆

发表于 2007-10-22 14:33:06 | 显示全部楼层
LS 说的对对啊

出0入0汤圆

发表于 2008-1-8 20:56:05 | 显示全部楼层
学习了,记号

出0入0汤圆

发表于 2008-2-19 14:53:51 | 显示全部楼层
支持,留个脚印,他日好用,谢谢了!

出0入0汤圆

发表于 2008-4-22 09:01:34 | 显示全部楼层

出0入0汤圆

发表于 2008-5-6 08:17:58 | 显示全部楼层
提供FAT文件系统

1)兼容FAT16文件系统,长文件名,最大路径长度260个字节,符合Microsoft Longfilename specification。
2)移植方便,只需编写sector驱动,共计两个函数:1)read_flash_sector() 2)write_flash_sector()。
3)具有文件缓冲功能:1)读文件时,读位置在文件缓冲区内,则可直接读文件缓冲区,不需要读物理磁盘;文件缓冲区大小可使用编译宏EnableFileBuf,TotalFileBUFsQTYeachFCB,FileBUFSize来控制。
4)能够同时打开多个文件;最大打开文件数可使用编译宏MaximumFCB设定,MaximumFCB最大值限定为254。
5)具有文件保护功能:文件可同时打开多个FCB,而只有其中一个FCB可以得到文件RD/WR权限。该功能完全由文件系统代码来完成,上层应用无需编写额外代码。
6)所有编译宏存放于文件fat_cfg.h。
7)支持文件读写,删除,改名,子目录,长文件名,文件查找,文件遍历等


联系作者:qq:292942278,e-mail:tony_yang@sina.com.cn

出0入0汤圆

发表于 2008-7-4 18:42:25 | 显示全部楼层
提供FAT16文件系统

本文件系统实现的一个类似于DOS/WINDOWS的文件管理系统,可方便的移植于各种嵌入式系统平台。本文件系统采用了文件缓冲块的技术,文件读写速度被加快。本文件系统可支持多个逻辑盘,可以方便的实现不同逻辑盘之间数据的搬移。本文件系统支持子目录,长文件名,为此,增加了许多额外的代码,使文件系统的整体开发变得复杂,但对上层来说应用变得简单,灵活,扩大了本文件系统的应用领域。本文件系统采用模块化的设计技术,因些性能稳定,构架清晰,系统二次开发方便。

QQ:292942278

出0入0汤圆

发表于 2008-7-4 20:29:26 | 显示全部楼层
学习一下,做电子书正好派上用场

出0入0汤圆

发表于 2008-10-16 14:06:01 | 显示全部楼层
学习

出0入0汤圆

发表于 2008-11-11 15:41:27 | 显示全部楼层
lz我有个问题,我用了你的程序,但是创建出来的。txt文件在pc机下看不来,但是用winhex可以这是怎么回事呢???????????请帮帮忙啊!!

出0入0汤圆

发表于 2008-11-11 21:54:59 | 显示全部楼层
顶一下,最近也在做这样,值得参考.

出0入0汤圆

发表于 2008-11-15 21:08:27 | 显示全部楼层
正在研究这方面,顶一下!

出0入0汤圆

发表于 2008-11-15 22:06:37 | 显示全部楼层
记号

出0入0汤圆

发表于 2008-11-16 18:17:20 | 显示全部楼层
这年头,牛人真多!!!!

出0入0汤圆

发表于 2008-11-17 12:19:02 | 显示全部楼层
很强大!感谢楼主

出0入0汤圆

发表于 2008-12-30 15:19:42 | 显示全部楼层
LZ继续努力哈~~

出0入0汤圆

发表于 2008-12-30 15:56:01 | 显示全部楼层
不错,学子下

出0入0汤圆

发表于 2009-1-1 23:23:20 | 显示全部楼层
学习了,谢谢LZ

出0入0汤圆

发表于 2009-10-31 18:33:34 | 显示全部楼层
顶楼主!!

出0入0汤圆

发表于 2010-4-7 22:25:52 | 显示全部楼层
mark!

出0入25汤圆

发表于 2010-4-7 23:02:22 | 显示全部楼层
顶下,mark!

出0入0汤圆

发表于 2010-4-7 23:26:36 | 显示全部楼层
mark!

出0入0汤圆

发表于 2010-9-8 18:22:57 | 显示全部楼层
正要学习了解这些,谢谢!

出0入0汤圆

发表于 2010-10-2 10:07:15 | 显示全部楼层
mark!!!!!!

出0入0汤圆

发表于 2010-11-27 00:14:13 | 显示全部楼层
强悍啊

出0入0汤圆

发表于 2010-12-12 14:24:55 | 显示全部楼层
好。正在学习这方面的知识。顶楼主。

出0入0汤圆

发表于 2011-6-18 19:36:21 | 显示全部楼层
嵌入式FAT文件系统免费源码下载

本文件系统兼容FAT16/FAT32文件系统格式,兼容长文件名,兼容GB2312/UNICODE汉字编码(支持中文),并且实现了对子目录的支持,实现了文件的读取,写入,创建,删除等文件系统的常用功能。另外,代码都使用C编写,可以移植到各种单片机平台上来实现文件系统模块。

(FAT16是免费代码,用户可直接使用。
本代码有FAT32(兼容FAT16)和多个盘的版本(收费),
如果需要,请与我们联系!qq:292942278,E-MAIL:tony_yang123@sina.com.cn)

点击此处下载 ourdev_650067SLJSIT.rar(文件大小:989K) (原文件名:FAT16.rar)

出0入0汤圆

发表于 2011-6-18 21:43:07 | 显示全部楼层
牛人啊

出0入0汤圆

发表于 2011-7-20 16:19:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-12 11:24:05 | 显示全部楼层
弱弱的问一句:这个很难吗?怎么都说牛人咧?

出0入0汤圆

 楼主| 发表于 2011-8-12 12:22:07 | 显示全部楼层
2005年的老帖,还是沉了吧。

出0入0汤圆

发表于 2011-8-12 13:05:06 | 显示全部楼层
MARK FAT16 文件系统

出0入0汤圆

发表于 2011-12-28 10:17:33 | 显示全部楼层
MARK

出0入0汤圆

发表于 2012-1-20 03:00:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-20 09:40:26 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 07:03

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表