znFAT移植与使用手册
以前用守的的FAT32文件系统。后面有时间了,我在CY的单片机上移植下,给大家分享下。 上传一个以前做的程序
关注下 /**************************************************************************
- 功能描述:创建文件(支持任意层目录创建)
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi:一个指向FileInfoStruct类型的结构体的指针,用来装载新创建的
文件信息,因此新创建的文件不用再打开就可以直接来操作
filepath:文件路径 比如 "\\dir1\\dir2\\dir3\\....\\dirn\\test.txt"
- 返回说明:0:成功 1:文件已存在 2:创建文件目录失败 3:创建文件失败
- 注:如果文件路径中某一个中间目录不存在,那么此函数会创建这个目录,再继续
去创建更深层的目录,一直到最后把文件创建完成。
创建文件失败有可能是因为存储设备空间不足,或是此文件已经存在
**************************************************************************/
#ifdef ZNFAT_CREATE_FILE
UINT8 znFAT_Create_File(struct FileInfoStruct *pfi,CONST INT8 *filepath,UINT8 *ptd)
{
if (znFAT_Open_File(pfi,filepath,0,1))
{
if (!znFAT_Create_Dir(filepath,ptd))
{
if (znFAT_Create_Rec(pfi,temp_dir_cluster,temp_dir_name,0,ptd)==(UINT8)(-1))
{
return 3;
}
}
else
{
return 2;
}
}
else
{
return 1;
}
return 0;
}
#endif /**************************************************************************
- 功能描述:在存储设备中创建一个文件/目录项
- 隶属模块:znFAT文件系统模块
- 函数属性:内部
- 参数说明:pfi:指向FileInfoStruct类型的结构体,用于装载刚创建的文件的信息
也就是说,如果创建的是目录,则此结构体不会被更新
cluster:在cluster这个簇中创建文件/目录项,用于实现在任意目录下
创建文件或目录,可以通过znFAT_Enter_Dir来获取某一个目录的开
始簇
name:文件/目录的名称
is_dir:指示要创建的是文件还是目录,文件与目录的创建方法是不同的
1表示创建目录 0表示创建文件
- 返回说明:成功返回1,失败返回-1
**************************************************************************/
#ifdef ZNFAT_CREATE_REC
UINT8 znFAT_Create_Rec(struct FileInfoStruct *pfi,UINT32 cluster,INT8 *name,UINT8 is_dir,UINT8 *ptd)
{
UINT32 iSec,iRec,temp_sec,temp_clu,new_clu,i,old_clu;
UINT8 flag=0;
UINT16 temp_Rec;
struct direntry *pRec;
struct File_Dir_Items *pitems;
Fill_Rec_Inf(&temp_rec,name,is_dir,ptd);
do
{
old_clu=cluster;
temp_sec=SOC(cluster);
for (iSec=temp_sec;iSec<(temp_sec+pArg->SectorsPerClust);iSec++)
{
znFAT_ReadSector(iSec,znFAT_Buffer);
pitems=(struct File_Dir_Items *)znFAT_Buffer;
for (iRec=0;iRec<FILE_DIR_ITEM_NUM;iRec++)
{
pRec=&(pitems->file_dir_items);
if ((pRec->deName)==0) //空目录项 //需求建新簇时清空簇
{
flag=1;
if (is_dir) //如果是目录,需要给它建立新簇,为了写入.和..
{
if (!(new_clu=znFAT_Find_Free_Clust(0))) return (UINT8)(-1); //减少一个空簇
znFAT_Modify_FAT(new_clu,0x0fffffff);
(temp_rec.deHighClust)=(new_clu&0x00ff0000)>>16;
(temp_rec.deHighClust)=(new_clu&0xff000000)>>24;
(temp_rec.deLowCluster)=(new_clu&0x000000ff);
(temp_rec.deLowCluster)=(new_clu&0x0000ff00)>>8;
}
znFAT_ReadSector(iSec,znFAT_Buffer);
for (i=0;i<FILE_DIR_ITEM_SIZE;i++) //把填充好的文件目录项写入扇区
{
((UINT8 *)pRec)=((UINT8 *)(&temp_rec));
}
znFAT_WriteSector(iSec,znFAT_Buffer);
temp_sec=iSec;
temp_Rec=iRec;
iRec=FILE_DIR_ITEM_NUM; //这两句是为了跳出循环
//break;
iSec=temp_sec+pArg->SectorsPerClust;
}
}
}
}
while (!flag && (cluster=znFAT_GetNextCluster(cluster))!=0x0fffffff);
if (!flag)
{
if (!(temp_clu=znFAT_Find_Free_Clust(0))) return (UINT8)(-1);
//printf("temp_clu:%d\n",temp_clu);
znFAT_Modify_FAT(temp_clu,0x0fffffff);
znFAT_Modify_FAT(old_clu,temp_clu);
temp_sec=SOC(temp_clu);
temp_Rec=0;
znFAT_ReadSector(temp_sec,znFAT_Buffer);
if (is_dir)
{
if (!(new_clu=znFAT_Find_Free_Clust(0))) return (UINT8)(-1);
znFAT_Modify_FAT(new_clu,0x0fffffff);
znFAT_ReadSector(temp_sec,znFAT_Buffer);
(temp_rec.deHighClust)=(new_clu&0x00ff0000)>>16;
(temp_rec.deHighClust)=(new_clu&0xff000000)>>24;
(temp_rec.deLowCluster)=(new_clu&0x000000ff);
(temp_rec.deLowCluster)=(new_clu&0x0000ff00)>>8;
}
for (i=0;i<FILE_DIR_ITEM_SIZE;i++)
{
znFAT_Buffer=((UINT8 *)(&temp_rec));
}
znFAT_WriteSector(temp_sec,znFAT_Buffer);
}
if (is_dir)
{
znFAT_Empty_Cluster(new_clu);
//printf("cur_clu:%d\n",new_clu);
Fill_Rec_Inf(&temp_rec,".",1,ptd);
(temp_rec.deHighClust)=(new_clu&0x00ff0000)>>16;
(temp_rec.deHighClust)=(new_clu&0xff000000)>>24;
(temp_rec.deLowCluster)=(new_clu&0x000000ff);
(temp_rec.deLowCluster)=(new_clu&0x0000ff00)>>8;
for (i=0;i<FILE_DIR_ITEM_SIZE;i++)
{
znFAT_Buffer=((UINT8 *)(&temp_rec));
}
Fill_Rec_Inf(&temp_rec,"..",1,ptd);
if (cluster==pArg->FirstDirClust)
{
(temp_rec.deHighClust)=0;
(temp_rec.deHighClust)=0;
(temp_rec.deLowCluster)=0;
(temp_rec.deLowCluster)=0;
}
else
{
(temp_rec.deHighClust)=(old_clu&0x00ff0000)>>16;
(temp_rec.deHighClust)=(old_clu&0xff000000)>>24;
(temp_rec.deLowCluster)=(old_clu&0x000000ff);
(temp_rec.deLowCluster)=(old_clu&0x0000ff00)>>8;
}
for (i=FILE_DIR_ITEM_SIZE;i<2*FILE_DIR_ITEM_SIZE;i++)
{
znFAT_Buffer=((UINT8 *)(&temp_rec));
}
//for(;i<pArg->BytesPerSector;i++) //再次清空,重复操作
//{
//znFAT_Buffer=0;
//}
temp_sec=SOC(new_clu);
znFAT_WriteSector(temp_sec,znFAT_Buffer);
}
else
{
StringCopy(pfi->FileName,name);
pfi->FileStartCluster=0;
pfi->FileCurCluster=0;
pfi->FileSize=0;
pfi->FileCurSector=0;
pfi->FileCurPos=0;
pfi->FileCurOffset=0;
pfi->Rec_Sec=temp_sec;
pfi->nRec=temp_Rec;
pfi->FileAttr=temp_rec.deAttributes; //属性
}
znFAT_Find_Free_Clust(1);
return 1;
}
#endif /**************************************************************************
- 功能描述:向某一个文件追加数据
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi:指向FileInfoStruct类型的结构体,用于装载刚创建的文件的信息
len:要追加的数据长度
pbuf:指向数据缓冲区的指针
- 返回说明:成功返回实际写入的数据长度,失败返回0
- 注:追加数据失败很有可能是存储设备已经没有空间了,也就是找不到空闲簇了
**************************************************************************/
#ifdef ZNFAT_ADD_DAT
UINT32 znFAT_Add_Dat(struct FileInfoStruct *pfi,UINT32 len,UINT8 *pbuf)
{
UINT32 i=0,counter=0,iSec,iClu;
UINT32 temp_sub,temp_file_size,new_clu,temp_sec;
struct direntry *prec;
if (len>0)
{
znFAT_ReadSector(pfi->Rec_Sec,znFAT_Buffer);
prec=((struct direntry *)(znFAT_Buffer))+pfi->nRec;
temp_file_size=LE2BE((prec->deFileSize),4);
if (!temp_file_size)
{
if (!(new_clu=znFAT_Find_Free_Clust(0))) return 0;
znFAT_Modify_FAT(new_clu,0x0fffffff);
pfi->FileStartCluster=new_clu;
pfi->FileCurCluster=pfi->FileStartCluster;
pfi->FileSize=0;
pfi->FileCurSector=SOC(pfi->FileCurCluster);
pfi->FileCurPos=0;
pfi->FileCurOffset=0;
znFAT_ReadSector(pfi->Rec_Sec,znFAT_Buffer);
(prec->deHighClust)=(new_clu&0x00ff0000)>>16;
(prec->deHighClust)=(new_clu&0xff000000)>>24;
(prec->deLowCluster)=(new_clu&0x000000ff);
(prec->deLowCluster)=(new_clu&0x0000ff00)>>8;
znFAT_WriteSector(pfi->Rec_Sec,znFAT_Buffer);
}
else
{
if (!(temp_file_size%(pArg->SectorsPerClust*pArg->BytesPerSector))) //在簇的最末尾临界地方,需要寻找新簇
{
znFAT_Seek_File(pfi,pfi->FileSize-1); //@@@待优化
if (!(new_clu=znFAT_Find_Free_Clust(0))) return 0;
znFAT_Modify_FAT(pfi->FileCurCluster,new_clu);
znFAT_Modify_FAT(new_clu,0x0fffffff);
}
znFAT_Seek_File(pfi,pfi->FileSize);
}
//iSec=pfi->FileCurSector;
znFAT_ReadSector(pfi->FileCurSector,znFAT_Buffer);
for (i=pfi->FileCurPos;i<pArg->BytesPerSector;i++)
{
znFAT_Buffer=pbuf;
counter++;
if (counter>=len)
{
iSec=pfi->FileCurSector;
goto end;
}
}
znFAT_WriteSector(pfi->FileCurSector,znFAT_Buffer); //数据接缝,把上次扇区剩余字节填充完
//printf("here1\n");
if ((pfi->FileCurSector-(SOC(pfi->FileCurCluster)))<(pArg->SectorsPerClust-1)) //判断是不是一个簇的最后一个扇区,先将当前簇所有扇区填满
{
for (iSec=pfi->FileCurSector+1;iSec<=(SOC(pfi->FileCurCluster)+pArg->SectorsPerClust-1);iSec++)
{
for (i=0;i<pArg->BytesPerSector;i++)
{
znFAT_Buffer=pbuf;
counter++;
//printf("##-->%d\n$$-->%d\n",counter,pbuf);
if (counter>=len)
{
goto end;
}
}
znFAT_WriteSector(iSec,znFAT_Buffer);
}
}
//printf("here2\n");
temp_sub=len-counter;
for (iClu=0;iClu<temp_sub/(pArg->SectorsPerClust*pArg->BytesPerSector);iClu++)
{
if (!(new_clu=znFAT_Find_Free_Clust(0))) return 0;
znFAT_Modify_FAT(pfi->FileCurCluster,new_clu);
znFAT_Modify_FAT(new_clu,0x0fffffff);
pfi->FileCurCluster=new_clu;
temp_sec=SOC(new_clu);
for (iSec=temp_sec;iSec<temp_sec+pArg->SectorsPerClust;iSec++)
{
for (i=0;i<pArg->BytesPerSector;i++)
{
znFAT_Buffer=pbuf;
counter++;
}
znFAT_WriteSector(iSec,znFAT_Buffer);
}
}
temp_sub=len-counter;
if (temp_sub)
{
if (!(new_clu=znFAT_Find_Free_Clust(0))) return 0;
znFAT_Modify_FAT(pfi->FileCurCluster,new_clu);
znFAT_Modify_FAT(new_clu,0x0fffffff);
pfi->FileCurCluster=new_clu;
temp_sec=SOC(new_clu);
for (iSec=temp_sec;iSec<temp_sec+temp_sub/pArg->BytesPerSector;iSec++)
{
for (i=0;i<pArg->BytesPerSector;i++)
{
znFAT_Buffer=pbuf;
counter++;
}
znFAT_WriteSector(iSec,znFAT_Buffer);
}
}
temp_sub=len-counter;
if (temp_sub)
{
for (i=0;i<pArg->BytesPerSector;i++)
{
znFAT_Buffer=pbuf;
counter++;
}
znFAT_WriteSector(iSec,znFAT_Buffer);
}
end:
//printf("here!\n");
znFAT_WriteSector(iSec,znFAT_Buffer);
znFAT_ReadSector(pfi->Rec_Sec,znFAT_Buffer);
((((struct direntry *)(znFAT_Buffer))+pfi->nRec)->deFileSize)=((temp_file_size+len)&0x000000ff);
((((struct direntry *)(znFAT_Buffer))+pfi->nRec)->deFileSize)=((temp_file_size+len)&0x0000ff00)>>8;
((((struct direntry *)(znFAT_Buffer))+pfi->nRec)->deFileSize)=((temp_file_size+len)&0x00ff0000)>>16;
((((struct direntry *)(znFAT_Buffer))+pfi->nRec)->deFileSize)=((temp_file_size+len)&0xff000000)>>24;
znFAT_WriteSector(pfi->Rec_Sec,znFAT_Buffer);
//printf("here pass\n");
pfi->FileSize=(temp_file_size+len);
pfi->FileCurSector=(pfi->FileSize%pArg->BytesPerSector)?iSec:iSec+1;
pfi->FileCurPos=pfi->FileSize%pArg->BytesPerSector;
pfi->FileCurOffset=pfi->FileSize;
//printf("==============================================\n");
//printf("FileSize:%d\n",pfi->FileSize);
//printf("FileCurSector:%d\n",pfi->FileCurSector);
// printf("FileCurPos:%d\n",pfi->FileCurPos);
// printf("FileCurOffset:%d\n",pfi->FileCurOffset);
//printf("==============================================\n");
}
znFAT_Find_Free_Clust(1);
//printf("here end\n");
return len;
}
#endif /**************************************************************************
- 功能描述:创建目录(支持任意层目录创建)
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi:无用
dirpath:目录路径 比如 "\\dir1\\dir2\\dir3\\....\\dirn\\"
最后必须是\\结束
- 返回说明:成功返回0,失败返回1
- 注:如果中间某一级目录不存在,比如上面的这个路径中dir3不存在,那么此函数会
创建这个目录,然后再继续去创建更深层的目录
创建目录失败有可能是因为存储设备空间不足
**************************************************************************/
#ifdef ZNFAT_CREATE_DIR
UINT8 znFAT_Create_Dir(CONST INT8 *dirpath,UINT8 *ptd)
{
struct FileInfoStruct *pfi;
while (!znFAT_Enter_Dir(dirpath))
{
if (znFAT_Create_Rec(pfi,temp_dir_cluster,temp_dir_name,1,ptd)==(UINT8)(-1))
{
return 1;
}
}
return 0;
}
#endif /**************************************************************************
- 功能描述:删除文件(支持任意层目录)
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:filepath:文件路径 比如 "\\dir1\\dir2\\dir3\\....\\dirn\\test.txt"
- 返回说明:1:文件或目录路径不存在 0:成功
- 注:删除后的文件的FAT表中的簇链关系完全被破坏
**************************************************************************/
#ifdef ZNFAT_DEL_FILE
UINT8 znFAT_Del_File(CONST INT8 *filepath)
{
UINT32 cur_clu,next_clu;
struct FileInfoStruct fi;
if (znFAT_Open_File(&fi,filepath,0,1))
{
return 1;
}
znFAT_ReadSector(fi.Rec_Sec,znFAT_Buffer);
*(znFAT_Buffer+fi.nRec)=0xe5;
znFAT_WriteSector(fi.Rec_Sec,znFAT_Buffer);
if (cur_clu=fi.FileStartCluster)
{
if (cur_clu<Search_Last_Usable_Cluster())
znFAT_Update_FSInfo_Last_Clu(cur_clu);
znFAT_Update_FSInfo_Free_Clu(1);
next_clu=znFAT_GetNextCluster(cur_clu);
while (next_clu!=0x0fffffff)
{
znFAT_Update_FSInfo_Free_Clu(1);
znFAT_Modify_FAT(cur_clu,0x00000000);
cur_clu=next_clu;
next_clu=znFAT_GetNextCluster(cur_clu);
}
znFAT_Modify_FAT(cur_clu,0x00000000);
}
return 0;
}
#endif /**************************************************************************
- 功能描述:文件拷贝(源文件路径与目标文件路径均支持任意深层目录,并且支持
文件名通配)
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pArg1:是源文件所在的存储设备的初始参数结构体的指针
pArg2:是目标文件所在的存储设备的初始参数结构体的指针
sfilename:源文件路径,也就是拷贝操作的数据源
tfilename:目标文件路径,也就是数据最终到写入的文件
比如 "\\dir1\\dir2\\dir3\\....\\dirn\\test.txt"
file_buf:拷贝过程中要用到的数据缓冲区,此缓冲区容量越大,
拷贝速度越快
buf_size:数据缓冲区的大小
- 返回说明:1:目录文件创建失败 2:源文件打开打败 0:成功
- 注:此函数支持多设备之间的文件拷贝,pArg1与pArg2引入了源存储设备与目的
存储设备的初始参数信息,从而可以同时对两个存储设备进行操作。
znFAT 5.01版开始支持多设备,多设备间的相互数据拷贝是最典型的应用
**************************************************************************/
#ifdef ZNFAT_XCOPY_FILE
UINT8 znFAT_XCopy_File(struct znFAT_Init_Arg *pArg1,struct znFAT_Init_Arg *pArg2,CONST INT8 *sfilename,CONST INT8 *tfilename,UINT8 *file_buf,UINT32 buf_size,UINT8 *pt)
{
struct FileInfoStruct FileInfo2,FileInfo1;
struct znFAT_Init_Arg *pArg_temp;
UINT32 i;
pArg_temp=pArg; //把pArg原来的指向赋给中间变量
pArg=pArg2;
Dev_No=pArg->DEV_No; //标定目标存储设备
if (znFAT_Create_File(&FileInfo1,tfilename,pt)) return 1; //在目标存储设备上创建目标文件
pArg=pArg1;
Dev_No=pArg->DEV_No; //标定源存储设备
if (znFAT_Open_File(&FileInfo2,sfilename,0,1)) return 2; //在源存储设备上打开源文件
for (i=0;i<FileInfo2.FileSize/buf_size;i++)
{
pArg=pArg1;
Dev_No=pArg->DEV_No; //标定源存储设备
znFAT_Read_File(&FileInfo2,i*buf_size,buf_size,file_buf); //读源存储设备上的源文件数据到数据缓冲区
pArg=pArg2;
Dev_No=pArg->DEV_No; //标定目标存储设备
znFAT_Add_Dat(&FileInfo1,buf_size,file_buf); //将数据级冲区的数据写入到目标文件中
}
pArg=pArg1;
Dev_No=pArg->DEV_No; //标定源存储设备
znFAT_Read_File(&FileInfo2,i*buf_size,FileInfo2.FileSize%buf_size,file_buf);//读取最后的文件余量
pArg=pArg2;
Dev_No=pArg->DEV_No; //标定目标存储设备
znFAT_Add_Dat(&FileInfo1,FileInfo2.FileSize%buf_size,file_buf); //将最后的余量数据写入到目标文件中
pArg=pArg_temp; //将pArg恢复
return 0;
}
#endif /**************************************************************************
- 功能描述:文件重命名
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:filename:将要重命名的源文件的路径 如\a.txt
newfilename:目标文件名 如b.txt (注目标文件名是单纯的文件名,
不含路径)
- 返回说明:1:源文件打开打败 0:成功
- 注:无
**************************************************************************/
#ifdef ZNFAT_RENAME_FILE
UINT8 znFAT_Rename_File(CONST INT8 *filename,CONST INT8 *newfilename)
{
struct FileInfoStruct fi;
UINT8 i=0,j=0;
if (znFAT_Open_File(&fi,filename,0,1)) return 1; //文件打开失败
znFAT_ReadSector(fi.Rec_Sec,znFAT_Buffer);
for (i=0;i<11;i++) (znFAT_Buffer+fi.nRec)=0x20;
i=0;
while (newfilename!='.')
{
(znFAT_Buffer+fi.nRec)=L2U(newfilename);
i++;
}
i++;
while (newfilename)
{
(znFAT_Buffer+fi.nRec+8)=L2U(newfilename);
i++;
j++;
}
znFAT_WriteSector(fi.Rec_Sec,znFAT_Buffer);
return 0;
}
#endif /**************************************************************************
- 功能描述:文件关闭
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi:指向当前打开的文件的文件信息结构
- 返回说明:0:成功
- 注:无
**************************************************************************/
#ifdef ZNFAT_FILE_CLOSE
UINT8 znFAT_File_Close(struct FileInfoStruct *pfi)
{
UINT16 i=0;
for (i=0;i<sizeof(struct FileInfoStruct);i++)
{
((UINT8 *)pfi)=0;
}
return 0;
}
#endif
/***********waiting***************************************************************
- 功能描述:从文件某一位置读取一定长度的数据,由pfun所指向的函数来处理
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi:FileInfoStruct类型的结构体指针,用于装载文件参数信息,文件
读取的过程中,此结构体中的相关参数会更新,比如文件的当前偏移量、
文件的当前扇区,文件的当前簇等等
offset:要定位的偏移量,要小于文件的大小
len:要读取的数据的长度,如果len+offset大于文件的大小,则实际读
取的数据量是从offset开始到文件结束
pfun:对读取的数据的处理函数,pfun指向处理函数,这样可以灵活的
配置数据如何去处理,比如是放在缓冲区中,还是把数据通过串口发送
出去,只需要pfun去指向相应的处理函数可以了
- 返回说明:读取到的实际的数据长度,如果读取失败,比如指定的偏移量大于了文件
大小,则返回0
- 注:在读取一个文件的数据前,必须先将该文件用znFAT_Open_File打开
**************************************************************************/
#ifdef ZNFAT_READ_FILEX
UINT32 znFAT_Read_FileX(struct FileInfoStruct *pfi,UINT32 offset,UINT32 len,void (*pfun)(UINT8))
{
UINT32 i,j,k,temp;
UINT32 counter=0;
if (offset<pfi->FileSize)
{
if (offset+len>pfi->FileSize) len=pfi->FileSize-offset;
znFAT_Seek_File(pfi,offset);
znFAT_ReadSector(pfi->FileCurSector,znFAT_Buffer);
for (i=pfi->FileCurPos;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
(*pfun)(znFAT_Buffer);
counter++;
pfi->FileCurPos++;
pfi->FileCurOffset++;
}
if (pfi->FileCurSector-(SOC(pfi->FileCurCluster))!=(pArg->SectorsPerClust-1))
{
for (j=pfi->FileCurSector+1;j<(SOC(pfi->FileCurCluster))+pArg->SectorsPerClust;j++)
{
znFAT_ReadSector(j,znFAT_Buffer);
pfi->FileCurSector=j;
for (i=0;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
(*pfun)(znFAT_Buffer);
counter++;
pfi->FileCurPos++;
pfi->FileCurOffset++;
}
}
}
temp=(len-counter)/(pArg->BytesPerSector*pArg->SectorsPerClust);
for (k=0;k<temp;k++)
{
pfi->FileCurCluster=znFAT_GetNextCluster(pfi->FileCurCluster);
for (j=(SOC(pfi->FileCurCluster));j<(SOC(pfi->FileCurCluster))+pArg->SectorsPerClust;j++)
{
znFAT_ReadSector(j,znFAT_Buffer);
pfi->FileCurSector=j;
for (i=0;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
(*pfun)(znFAT_Buffer);
counter++;
pfi->FileCurOffset++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
}
}
}
pfi->FileCurCluster=znFAT_GetNextCluster(pfi->FileCurCluster);
temp=(SOC(pfi->FileCurCluster))+((len-counter)/pArg->BytesPerSector);
pfi->FileCurSector=(SOC(pfi->FileCurCluster));
for (j=(SOC(pfi->FileCurCluster));j<temp;j++)
{
znFAT_ReadSector(j,znFAT_Buffer);
pfi->FileCurSector=j;
for (i=0;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
(*pfun)(znFAT_Buffer);
counter++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
pfi->FileCurOffset++;
}
}
pfi->FileCurSector=j;
znFAT_ReadSector(pfi->FileCurSector,znFAT_Buffer);
temp=len-counter;
for (i=0;i<temp;i++)
{
if (counter>=len)
{
return len;
}
(*pfun)(znFAT_Buffer);
counter++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
pfi->FileCurOffset++;
}
}
else
{
len=0;
}
return len;
}
#endif /**************************************************************************
- 功能描述:从文件的某一个位置处,读取一定长度的数据,放入数据缓冲区中
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi:FileInfoStruct类型的结构体指针,用于装载文件参数信息,文件
读取的过程中,此结构体中的相关参数会更新,比如文件的当前偏移量、
文件的当前扇区,文件的当前簇等等
offset:要定位的偏移量,要小于文件的大小
len:要读取的数据的长度,如果len+offset大于文件的大小,则实际读
取的数据量是从offset开始到文件结束
pbuf:数据缓冲区
- 返回说明:读取到的实际的数据长度,如果读取失败,比如指定的偏移量大于了文件
大小,则返回0
- 注:在读取一个文件的数据前,必须先将该文件用znFAT_Open_File打开
**************************************************************************/
#ifdef ZNFAT_READ_FILE
UINT32 znFAT_Read_File(struct FileInfoStruct *pfi,UINT32 offset,UINT32 len,UINT8 *pbuf)
{
UINT32 j,k,temp;
UINT32 counter=0;
UINT16 i;
if (offset<pfi->FileSize)
{
if (offset+len>pfi->FileSize) len=pfi->FileSize-offset;
znFAT_Seek_File(pfi,offset);
znFAT_ReadSector(pfi->FileCurSector,znFAT_Buffer);
for (i=pfi->FileCurPos;i<pArg->BytesPerSector;i++) //扇区内数据余量
{
if (counter>=len)
{
return len;
}
pbuf=znFAT_Buffer;
counter++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
pfi->FileCurOffset++;
}
if (((pfi->FileCurSector)-(SOC(pfi->FileCurCluster)))!=(pArg->SectorsPerClust-1))
{
temp=(SOC(pfi->FileCurCluster))+pArg->SectorsPerClust;
for (j=(pfi->FileCurSector+1);j<temp;j++) //簇内扇区数据余量
{
znFAT_ReadSector(j,znFAT_Buffer);
pfi->FileCurSector=j;
for (i=0;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
pbuf=znFAT_Buffer;
counter++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
pfi->FileCurOffset++;
}
}
}
temp=(len-counter)/(pArg->BytesPerSector*pArg->SectorsPerClust);
for (k=0;k<temp;k++)
{
pfi->FileCurCluster=znFAT_GetNextCluster(pfi->FileCurCluster);
for (j=(SOC(pfi->FileCurCluster));j<(SOC(pfi->FileCurCluster))+pArg->SectorsPerClust;j++)
{
znFAT_ReadSector(j,znFAT_Buffer);
pfi->FileCurSector=j;
for (i=0;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
pbuf=znFAT_Buffer;
counter++;
pfi->FileCurOffset++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
}
}
}
pfi->FileCurCluster=znFAT_GetNextCluster(pfi->FileCurCluster);
temp=(SOC(pfi->FileCurCluster))+((len-counter)/pArg->BytesPerSector);
pfi->FileCurSector=(SOC(pfi->FileCurCluster));
for (j=(SOC(pfi->FileCurCluster));j<temp;j++)
{
znFAT_ReadSector(j,znFAT_Buffer);
pfi->FileCurSector=j;
for (i=0;i<pArg->BytesPerSector;i++)
{
if (counter>=len)
{
return len;
}
pbuf=znFAT_Buffer;
counter++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
pfi->FileCurOffset++;
}
}
pfi->FileCurSector=j;
znFAT_ReadSector(pfi->FileCurSector,znFAT_Buffer);
temp=len-counter;
for (i=0;i<temp;i++)
{
if (counter>=len)
{
return len;
}
pbuf=znFAT_Buffer;
counter++;
pfi->FileCurPos++;
pfi->FileCurPos%=pArg->BytesPerSector;
pfi->FileCurOffset++;
}
}
else
{
len=0;
}
return len;
}
#endif /**************************************************************************
- 功能描述:打开一个文件(支持文件名通配,如 A*.txt 或 *.*)
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:pfi: FileInfoStruct类型的结构体指针,用来装载文件的参数信息
比如文件的大小、文件的名称、文件的开始簇等等,以备后面使用
filepath: 文件的路径,支持任意层目录 比如
"\\dir1\\dir2\\dir3\\....\\test.txt"
item:在文件名中有通配符*或?的情况下,实现与之匹配的文件并非
一个,item就是打开的文件的项数,比如符合通配条件的文件有6个,
如果item=3,那么此函数就会打开这6个文件中按顺序排号为3的那个
文件(item编号从0开始)
- 返回说明:0:成功 1:文件不存在 2:目录不存在
- 注:打开文件不成功有很多原因,比如文件不存在、文件的某一级目录不存在
通配情况下满足条件的文件项数小于item的值等等
通常情况下,文件名中没有通配符,item的值我们取0就可以了
**************************************************************************/
#ifdef ZNFAT_OPEN_FILE
UINT8 znFAT_Open_File(struct FileInfoStruct *pfi,CONST INT8 *filepath,UINT32 item,UINT8 is_file)
{
UINT32 Cur_Clust,sec_temp,iSec,iFile,iItem=0;
UINT8 flag=0,index=0;
UINT8 i=0,start_pos=0,counter=0;
struct direntry *pFile;
struct File_Dir_Items *pitems;
INT8 temp_file_name;
while (filepath!=0)
{
if (filepath=='\\') index=i;
i++;
}
if (Cur_Clust=znFAT_Enter_Dir(filepath))
{
do
{
sec_temp=SOC(Cur_Clust);
for (iSec=sec_temp;iSec<sec_temp+pArg->SectorsPerClust;iSec++)
{
znFAT_ReadSector(iSec,znFAT_Buffer);
pitems=(struct File_Dir_Items *)znFAT_Buffer;
for (iFile=0;iFile<FILE_DIR_ITEM_NUM;iFile++)
{
pFile=&(pitems->file_dir_items);
if (en_longname)
{
if (((struct LongNameItem*)pFile)->mark==0x0f && (pFile->deName!=0xe5))
{
if (((struct LongNameItem*)pFile)->n_item&0x40)
{
is_longname=1;
}
if (is_longname)
{
counter=0;
start_pos=((((struct LongNameItem*)pFile)->n_item&0xbf)-1)*26;
for (i=1;i<11;i++)
{
longname_buf=((UINT8 *)pFile);
counter++;
}
for (i=14;i<26;i++)
{
longname_buf=((UINT8 *)pFile);
counter++;
}
for (i=28;i<32;i++)
{
longname_buf=((UINT8 *)pFile);
counter++;
}
}
}
}
if (pFile->deAttributes & (is_file?0x20:0x10))
{
//if(!is_longname) is_longname=0;
znFAT_toFileName((INT8 *)(pFile->deName),temp_file_name);
//printf("time-> %d temp_file_name->%s\n",h++,temp_file_name);
//printf("temp_dir_name->%s\n",temp_dir_name);
//printf("cur_clust->%d sec->%d\n",Cur_Clust,iSec);
if (!is_file) //如果是目录,把点去掉
{
//i=0;
//while(temp_dir_name!=0) {if(temp_dir_name=='.') h=1;}
//if(!h) {temp_dir_name='.';temp_dir_name=0;}//补齐文件名 如果传进来的文件名没有扩展名,在后面加一个.
i=StrLen(temp_file_name);
temp_file_name=0;
}
if ((FilenameMatch(temp_dir_name,temp_file_name)) && (pFile->deName!=0xe5) && pFile->deAttributes & (is_file?0x20:0x10)) //匹配文件名,文件没有被删除,是文件或目录
{
if (item==iItem)
{
flag=1;
Cur_Clust=LE2BE(pFile->deLowCluster,2)+LE2BE(pFile->deHighClust,2)*65536;
pfi->FileSize=LE2BE(pFile->deFileSize,4);
if (pFile->deAttributes&0x10)
temp_file_name=0;
StringCopy(pfi->FileName,temp_file_name);
pfi->FileStartCluster=LE2BE(pFile->deLowCluster,2)+LE2BE(pFile->deHighClust,2)*65536;
pfi->FileCurCluster=pfi->FileStartCluster;
pfi->FileCurSector=SOC(pfi->FileStartCluster);
pfi->FileCurPos=0;
pfi->FileCurOffset=0;
pfi->Rec_Sec=iSec;
pfi->nRec=iFile;
pfi->FileAttr=pFile->deAttributes;
sec_temp=LE2BE(pFile->deCTime,2);
(pfi->FileCreateTime).sec=(sec_temp&0x001f)*2;
(pfi->FileCreateTime).min=((sec_temp>>5)&0x003f);
(pfi->FileCreateTime).hour=((sec_temp>>11)&0x001f);
sec_temp=LE2BE(pFile->deCDate,2);
(pfi->FileCreateDate).day=((sec_temp)&0x001f);
(pfi->FileCreateDate).month=((sec_temp>>5)&0x000f);
(pfi->FileCreateDate).year=((sec_temp>>9)&0x007f)+1980;
sec_temp=LE2BE(pFile->deMTime,2);
(pfi->FileMTime).sec=(sec_temp&0x001f)*2;
(pfi->FileMTime).min=((sec_temp>>5)&0x003f);
(pfi->FileMTime).hour=((sec_temp>>11)&0x001f);
sec_temp=LE2BE(pFile->deMDate,2);
(pfi->FileMDate).day=((sec_temp)&0x001f);
(pfi->FileMDate).month=((sec_temp>>5)&0x000f);
(pfi->FileMDate).year=((sec_temp>>9)&0x007f)+1980;
sec_temp=LE2BE(pFile->deADate,2);
(pfi->FileADate).day=((sec_temp)&0x001f);
(pfi->FileADate).month=((sec_temp>>5)&0x000f);
(pfi->FileADate).year=((sec_temp>>9)&0x007f)+1980;
iFile=pArg->BytesPerSector;
iSec=sec_temp+pArg->SectorsPerClust;
}
else
{
iItem++;
}
}
else
{
is_longname=0;
}
}
}
}
}
while (!flag && (Cur_Clust=znFAT_GetNextCluster(Cur_Clust))!=0x0fffffff);
if (!flag)
{
return 1;
}
return 0;
}
else
{
return 2;
}
}
#endif /***********************************************************************
- 功能描述:znFAT文件系统初始化
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:znFAT_Init_Arg类型的结构体指针,用于装载一些重要的参数信息,
以备后面使用
- 返回说明:无
- 注:在使用znFAT前,这个函数是必须先被调用的,将很多参数信息装入到
arg指向的结构体中,比如扇区大小、根目录的位置、FAT表大小等等。
这些参数绝大部分是来自于DBR的BPB中,因此此函数主要在作对DBR的参数解析
***********************************************************************/
void znFAT_Init(void)
{
struct znFAT_BPB *bpb;
bpb=(struct znFAT_BPB *)(znFAT_Buffer); //将数据缓冲区指针转为struct znFAT_BPB 型指针
pArg->DEV_No=Dev_No; //装入设备号
pArg->BPB_Sector_No =znFAT_Find_DBR(); //znFAT_FindBPB()可以返回BPB所在的扇区号
znFAT_ReadSector(pArg->BPB_Sector_No,znFAT_Buffer);
pArg->FATsectors =LE2BE((bpb->BPB_FATSz32) ,4);//装入FAT表占用的扇区数到FATsectors中
pArg->FirstDirClust =LE2BE((bpb->BPB_RootClus) ,4);//装入根目录簇号到FirstDirClust中
pArg->BytesPerSector=LE2BE((bpb->BPB_BytesPerSec),2);//装入每扇区字节数到BytesPerSector中
pArg->SectorsPerClust =LE2BE((bpb->BPB_SecPerClus) ,1);//装入每簇扇区数到SectorsPerClust 中
pArg->FirstFATSector=LE2BE((bpb->BPB_RsvdSecCnt) ,2)+pArg->BPB_Sector_No;//装入第一个FAT表扇区号到FirstFATSector 中
pArg->FirstDirSector=(pArg->FirstFATSector)+(bpb->BPB_NumFATs)*(pArg->FATsectors); //装入第一个目录扇区到FirstDirSector中
pArg->Total_Size =LE2BE((bpb->BPB_TotSec32),4)*pArg->BytesPerSector; //磁盘的总容量,单位是字节
temp_last_cluster=Search_Last_Usable_Cluster();
}
/******************************************************************
- 功能描述:znFAT的存储设备底层驱动接口,读取存储设备的addr扇区的
512个字节的数据放入buf数据缓冲区中
- 隶属模块:znFAT文件系统模块
- 函数属性:内部(用于与存储设备的底层驱动对接)
- 参数说明:addr:扇区地址
buf:指向数据缓冲区的指针
- 返回说明:0表示读取扇区成功,否则失败
- 注:这里加入了天狼星精华板上的三种存储设备,即SD卡(有效)、U盘、
CF卡通过在程序中动态的切换不同的设备驱动,从而实现多设备(即同
时对多种存储设备进行操作,比如从SD卡拷贝文件到U盘等等),不同
驱动的切换,只需要在程序中改变Dev_No这个全局变量的值即可
******************************************************************/
UINT8 znFAT_ReadSector(UINT32 addr,UINT8 *buf)
{
switch (Dev_No) //由Dev_No来决定所使用的存储设备驱动
{
case SDCARD:
return SD_Read_Sector(addr,buf);
break;
case UDISK:
//return CH375_Read_Sector(addr,buf);
break;
case CFCARD:
//return CF_Read_Sector(addr,buf);
break;
case OTHER:
//return PCSECTOR_Read_Sector(addr,buf);
break;
}
}
/******************************************************************
- 功能描述:znFAT的存储设备底层驱动接口,将buf数据缓冲区中的512个
字节的数据写入到存储设备的addr扇区中
- 隶属模块:znFAT文件系统模块
- 函数属性:内部(用于与存储设备的底层驱动对接)
- 参数说明:addr:扇区地址
buf:指向数据缓冲区
- 返回说明:0表示读取扇区成功,否则失败
- 注:略
******************************************************************/
UINT8 znFAT_WriteSector(UINT32 addr,UINT8 *buf)
{
switch (Dev_No) //由Dev_No来决定所使用的存储设备驱动
{
case SDCARD:
return SD_Write_Sector(addr,buf);
break;
case UDISK:
//return CH375_Write_Sector(addr,buf);
break;
case CFCARD:
//return CF_WriteSector(addr,buf);
break;
case OTHER:
//return PCSECTOR_Write_Sector(addr,buf);
break;
}
} 顶下,学习了 学习了,文件系统,应该很强吧
页:
[1]
2