zheng522 发表于 2015-4-23 23:29

znFAT移植与使用手册

以前用守的的FAT32文件系统。

zheng522 发表于 2015-4-23 23:30

后面有时间了,我在CY的单片机上移植下,给大家分享下。

zheng522 发表于 2015-4-23 23:36

上传一个以前做的程序

波越 发表于 2015-4-25 10:37

关注下

zheng522 发表于 2015-4-25 10:40

/**************************************************************************
- 功能描述:创建文件(支持任意层目录创建)
- 隶属模块: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

zheng522 发表于 2015-4-25 10:41

/**************************************************************************
- 功能描述:在存储设备中创建一个文件/目录项
- 隶属模块: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

zheng522 发表于 2015-4-25 10:41

/**************************************************************************
- 功能描述:向某一个文件追加数据
- 隶属模块: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

zheng522 发表于 2015-4-25 10:41

/**************************************************************************
- 功能描述:创建目录(支持任意层目录创建)
- 隶属模块: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

zheng522 发表于 2015-4-25 10:42

/**************************************************************************
- 功能描述:删除文件(支持任意层目录)
- 隶属模块: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

zheng522 发表于 2015-4-25 10:42

/**************************************************************************
- 功能描述:文件拷贝(源文件路径与目标文件路径均支持任意深层目录,并且支持
             文件名通配)
- 隶属模块: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

zheng522 发表于 2015-4-25 10:42

/**************************************************************************
- 功能描述:文件重命名
- 隶属模块: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

zheng522 发表于 2015-4-25 10:42

/**************************************************************************
- 功能描述:文件关闭
- 隶属模块: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

zheng522 发表于 2015-4-25 10:43

/***********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

zheng522 发表于 2015-4-25 10:44

/**************************************************************************
- 功能描述:从文件的某一个位置处,读取一定长度的数据,放入数据缓冲区中
- 隶属模块: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

zheng522 发表于 2015-4-25 10:44

/**************************************************************************
- 功能描述:打开一个文件(支持文件名通配,如 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

zheng522 发表于 2015-4-25 10:45

/***********************************************************************
- 功能描述: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();
}

zheng522 发表于 2015-4-25 10:46

/******************************************************************
- 功能描述: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;
    }
}

zheng522 发表于 2015-4-25 10:46

/******************************************************************
- 功能描述: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;
    }
}

波越 发表于 2015-4-26 00:49

顶下,学习了

给力芯片 发表于 2015-4-26 01:16

学习了,文件系统,应该很强吧
页: [1] 2
查看完整版本: znFAT移植与使用手册