⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 SD卡调试所用的资料
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "fat.h"
#include "sd.h"        //存储设备的扇区读写驱动,这里是SD卡
#include "string.h"

//全局变量定义
struct direntry idata temp_rec;
INT8 temp_dir_name[13]; 
UINT32 temp_dir_cluster;
UINT32 temp_last_cluster;

UINT8 FAT32_Buffer[512]; //扇区数据读写缓冲区,由外部提供

extern struct FAT32_Init_Arg *pArg; //初始化参数结构体指针,用以指向某一存储设备的初始化参数结构体,由外部提供

unsigned char (*pRS)(unsigned long,unsigned char *); //指向实际存储设备的读扇区函数的函数指针,用以实现对设备的支持
unsigned char (*pWS)(unsigned long,unsigned char *); //指向实际存储设备的写扇区函数的函数指针,用以实现对设备的支持

extern unsigned char Dev_No;

/******************************************************************
 - 功能描述:FAT的存储设备底层驱动接口,读取存储设备的addr扇区的
             512个字节的数据放入buf数据缓冲区中
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部(用于与存储设备的底层驱动对接)
 - 参数说明:addr:扇区地址
             buf:指向数据缓冲区
 - 返回说明:0表示读取扇区成功,否则失败
 - 注:这里加入了天狼星精华板上的三种存储设备,即SD卡(有效)、U盘、
       CF卡通过在程序中动态的切换不同的设备驱动,从而实现多设备(即同
	   时对多种存储设备进行操作,比如从SD卡拷贝文件到U盘等等),不同
	   驱动的切换,只需要在程序中改变Dev_No这个全局变量的值即可
 ******************************************************************/

UINT8 FAT32_ReadSector(UINT32 addr,UINT8 *buf) 
{
 switch(Dev_No)
 {
  case SDCARD:
         pRS=SD_Read_Sector;
         break;
  case UDISK:
         //pRS=CH375_Read_Sector;
         break;
  case CFCARD:
         //pRS=CF_Read_Sector;
         //无
         break;
  case OTHER:
         //无
         break;
 }
 return (*pRS)(addr,buf);  //替换成实际存储器的扇区读函数,这里是SD卡扇区读函数
}

/******************************************************************
 - 功能描述:FAT的存储设备底层驱动接口,将buf数据缓冲区中的512个
             字节的数据写入到存储设备的addr扇区中
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部(用于与存储设备的底层驱动对接)
 - 参数说明:addr:扇区地址
             buf:指向数据缓冲区
 - 返回说明:0表示读取扇区成功,否则失败
 - 注:略
 ******************************************************************/

UINT8 FAT32_WriteSector(UINT32 addr,UINT8 *buf)
{
 switch(Dev_No)
 {
  case SDCARD:
         pWS=SD_Write_Sector;
         break;
  case UDISK:
         //pWS=CH375_Write_Sector;
         break;
  case CFCARD:
         //pWS=CF_Write_Sector;
         //无
         break;
  case OTHER:
         //无
         break;
 }
 return (*pWS)(addr,buf); //替换成实际存储器的扇区写函数,这里是SD卡扇区写函数
}

/******************************************************************
 - 功能描述:小端转大端,即LittleEndian车BigEndian
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:dat:指向要转为大端的字节序列
             len:要转为大端的字节序列长度
 - 返回说明:转为大端模式后,字节序列所表达的数据
 - 注:比如:小端模式的       0x33 0x22 0x11 0x00  (低字节在前)
             转为大端模式后为 0x00 0x11 0x22 0x33  (高字节在前)
             所表达的数值为   0x00112233
             (CISC的CPU通常是小端的,所以FAT32也设计为小端,而单片机
              这种RISC的CPU,通常来说都是大端的,所以需要这个函数将字
              节的存放次序进行调整,才能得到正确的数值)
 ******************************************************************/

UINT32 LE2BE(UINT8 *dat,UINT8 len) 
{
 UINT32 temp=0;
 UINT32 fact=1;
 UINT8  i=0;
 for(i=0;i<len;i++)
 {
  temp+=dat[i]*fact; //将各字节乘以相应的权值后累加
  fact*=256; //更新权值
 }
 return temp;
}

/******************************************************************
 - 功能描述:将小字字符转为大写
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:c:要转换为大写的字符            
 - 返回说明:要转换的字节的相应的大写字符
 - 注:只对小写字符有效,如果不是a~z的小写字符,将直接返回
 ******************************************************************/

INT8 L2U(INT8 c)
{
 if(c>='a' && c<='z') return c+'A'-'a';
 else return c;
}

/******************************************************************
 - 功能描述:读取0扇区,检测有没有MBR(主引导记录)
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:无     
 - 返回说明:1表示检测到MBR,0表示没有检测到MBR
 - 注:有些存储设备格式化为FAT32以后,没有MBR,则0扇区就是DBR
       如果有MBR,就需要对其进行解析,以得到DBR的扇区位置,同时MBR中
       还含分区、分区容量等信息
 ******************************************************************/

UINT8 FAT32_is_MBR()
{
 UINT8 result;
 FAT32_ReadSector(0,FAT32_Buffer);
 if(FAT32_Buffer[0]!=0xeb) 
 {
  result=1;
 }
 else 
 {
  result=0;
 }
 return result;
}

/***********************************************************************
 - 功能描述:得到DBR所在的扇区号(如果没有MBR,则DBR就在0扇区)
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:无     
 - 返回说明:DBR的扇区地址
 - 注:DBR中包含了很多有用的参数信息,因此正确定位DBR扇区的位置,是极为
       重要的,后面将有专门的函数对DBR进行解析,正确解析DBR是实现FAT32的
       基础
 ***********************************************************************/

UINT16 FAT32_Find_DBR()
{
 UINT16 sec_dbr;
 FAT32_ReadSector(0,FAT32_Buffer);
 if(FAT32_Buffer[0]!=0xeb) 
 {
  sec_dbr=LE2BE(((((struct PartSector *)(FAT32_Buffer))->Part[0]).StartLBA),4);
 }
 else
 {
  sec_dbr=0;
 }
 return sec_dbr;
}

/***********************************************************************
 - 功能描述:获取分区的总容量
 - 隶属模块:FAT文件系统模块
 - 函数属性:外部,使用户使用
 - 参数说明:无     
 - 返回说明:分区容量值,单位为字节
 - 注:这里得到的总容量是FAT32分区的容量,一定小于实际的物理容量
 ***********************************************************************/

UINT32 FAT32_Get_Total_Size() 
{
 UINT32 temp;
 FAT32_ReadSector(pArg->BPB_Sector_No,FAT32_Buffer);
 FAT32_ReadSector(pArg->BPB_Sector_No,FAT32_Buffer);
 temp=((LE2BE((((struct FAT32_BPB *)(FAT32_Buffer))->BPB_TotSec32),4)))*pArg->BytesPerSector;
 return temp;
}

/***********************************************************************
 - 功能描述:读取FSInfo获取最近的一个可用空闲簇
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:无     
 - 返回说明:最近的一个可用空闲簇
 - 注:FAT32中的FSInfo扇区(绝对1扇区)中记录了最近的一个可用空闲簇
 ***********************************************************************/

UINT32 Search_Last_Usable_Cluster()
{
 FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
 return LE2BE(((struct FSInfo *)FAT32_Buffer)->Last_Cluster,4);
}

/***********************************************************************
 - 功能描述:FAT32文件系统初始化
 - 隶属模块:FAT文件系统模块
 - 函数属性:外部,使用户使用
 - 参数说明:FAT32_Init_Arg类型的结构体指针,用于装载一些重要的参数信息,
             以备后面使用     
 - 返回说明:无
 - 注:在使用znFAT前,这个函数是必须先被调用的,将很多参数信息装入到
       arg指向的结构体中,比如扇区大小、根目录的位置、FAT表大小等等。
       这些参数绝大部分是来自于DBR的BPB中,因此此函数主要在作对DBR的参数解析
 ***********************************************************************/

void FAT32_Init()
{
 struct FAT32_BPB *bpb;

 bpb=(struct FAT32_BPB *)(FAT32_Buffer);               //将数据缓冲区指针转为struct FAT32_BPB 型指针

 pArg->DEV_No=Dev_No; //装入设备号

 pArg->BPB_Sector_No   =FAT32_Find_DBR();               //FAT32_FindBPB()可以返回BPB所在的扇区号
 pArg->BPB_Sector_No   =FAT32_Find_DBR();               //FAT32_FindBPB()可以返回BPB所在的扇区号
 pArg->Total_Size      =FAT32_Get_Total_Size();         //FAT32_Get_Total_Size()可以返回磁盘的总容量,单位是字节
 pArg->Total_Size      =FAT32_Get_Total_Size();         //FAT32_Get_Total_Size()可以返回磁盘的总容量,单位是兆

 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[0])*(pArg->FATsectors); //装入第一个目录扇区到FirstDirSector中

 temp_last_cluster=Search_Last_Usable_Cluster();
}

/***********************************************************************
 - 功能描述:获取剩余容量
 - 隶属模块:FAT文件系统模块
 - 函数属性:外部,使用户使用
 - 参数说明:无    
 - 返回说明:剩余容量,单位字节
 - 注:从FSInfo中读取空闲簇数,而从计算得到剩余的容量,单位字节
 ***********************************************************************/

UINT32 FAT32_Get_Remain_Cap()
{
 FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
 if(((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]==0xff 
 && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]==0xff 
 && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]==0xff 
 && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]==0xff)
 return pArg->Total_Size;
 else
 return LE2BE(((struct FSInfo *)FAT32_Buffer)->Free_Cluster,4)*pArg->SectorsPerClust*pArg->BytesPerSector; 
}

/***********************************************************************
 - 功能描述:更新FSInfo中的可用空闲簇的数量
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:PlusOrMinus:可用空闲簇数加1或减1    
 - 返回说明:无
 - 注:创建文件、追加数据、删除文件等操作都可能会使可用的空闲簇数变化
       要及时更新
 ***********************************************************************/

void FAT32_Update_FSInfo_Free_Clu(UINT32 PlusOrMinus)
{
 UINT32 Free_Clu=0;
 FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);

 Free_Clu=(FAT32_Get_Remain_Cap())/(pArg->SectorsPerClust*pArg->BytesPerSector);

 if(PlusOrMinus) Free_Clu++;
 else Free_Clu--;

 ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]=((unsigned char *)&Free_Clu)[3]; 
 ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]=((unsigned char *)&Free_Clu)[2];
 ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]=((unsigned char *)&Free_Clu)[1];
 ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]=((unsigned char *)&Free_Clu)[0];
 FAT32_WriteSector(1+pArg->BPB_Sector_No,FAT32_Buffer);   
}

/***********************************************************************
 - 功能描述:更新FSInfo中的下一个可用空闲簇的簇号
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:Last_Clu:将要更新到FSInfo中的下一个可用空闲簇的簇号    
 - 返回说明:无
 - 注:FSInfo中的下一个可用空闲簇号可以给文件系统一个参考,直接告诉文件系统
       下一个可用的空闲簇在什么地方
 ***********************************************************************/

void FAT32_Update_FSInfo_Last_Clu(UINT32 Last_Clu)
{
 FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);  
 ((struct FSInfo *)FAT32_Buffer)->Last_Cluster[0]=((unsigned char *)&Last_Clu)[3]; 
 ((struct FSInfo *)FAT32_Buffer)->Last_Cluster[1]=((unsigned char *)&Last_Clu)[2];
 ((struct FSInfo *)FAT32_Buffer)->Last_Cluster[2]=((unsigned char *)&Last_Clu)[1];
 ((struct FSInfo *)FAT32_Buffer)->Last_Cluster[3]=((unsigned char *)&Last_Clu)[0];
 FAT32_WriteSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
}

/***********************************************************************
 - 功能描述:获得下一个簇的簇号
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:LastCluster:基准簇号  
 - 返回说明:LastClutster的下一簇的簇号
 - 注:获得下一簇的簇号,就是凭借FAT表中所记录的簇链关系来实现的
 ***********************************************************************/

UINT32 FAT32_GetNextCluster(UINT32 LastCluster)
{
 UINT32 temp;
 struct FAT32_FAT *pFAT;
 struct FAT32_FAT_Item *pFAT_Item;
 temp=((LastCluster/128)+pArg->FirstFATSector);
 FAT32_ReadSector(temp,FAT32_Buffer);
 pFAT=(struct FAT32_FAT *)FAT32_Buffer;
 pFAT_Item=&((pFAT->Items)[LastCluster%128]);
 return LE2BE((UINT8 *)pFAT_Item,4);
}

/***********************************************************************
 - 功能描述:比较目录名
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:a:指向目录名1的指针
             b:指向目录名2的指针
 - 返回说明:如果两个目录名相同就返回1,否则为0
 ***********************************************************************/

UINT8 Compare_Dir_Name(INT8 *a,INT8 *b)
{
 UINT8 i;
 for(i=0;i<8;i++)
 {
  if(a[i]!=b[i]) return 0;
 }
 return 1;
}

/***********************************************************************
 - 功能描述:文件名匹配(支持带*?通配符的文件名的匹配)
 - 隶属模块:FAT文件系统模块
 - 函数属性:内部
 - 参数说明:pat:源文件名,可以含*或?通配符 如 *.txt 或 A?.mp3等等
             name:目标文件名
 - 返回说明:如果两个文件名匹配就返回1,否则为0
 - 注:关于通配文件名匹配,有这样的例子,比如 A*.txt 与 ABC.txt是匹配的
   同时与 ABCDE.txt也是匹配的。此功能在文件枚举中将会用到,用来匹配
   文件名符合一定条件的文件
 ***********************************************************************/

UINT8 FilenameMatch(INT8 *pat,INT8 *name)
{
 INT16 match,ndone;
 INT8 *cpp,*cpn;
 cpp=pat;
 cpn=name;
 match=1;
 ndone=1;
 while(ndone)
 {
  switch (*cpp)
  {
   case '*':
            cpp++;
            cpn=strchr(cpn,*cpp);
            if(cpn==NULL)
            {
             cpn=name;
             while(*cpn) cpn++;
            }
            break;
   case '?':
            cpp++;
            cpn++;
            break;
   case 0:
            if(*cpn!=0)
            match=0;
            ndone=0;
            break;
   default:
            if((*cpp)==(*cpn))
            {
             cpp++;
             cpn++;
            }
            else
            {
             match=0;
             ndone=0;
            }
            break;
  }
 }
 return(match);
}

/***********************************************************************
 - 功能描述:FAT32的文件目录项的文件名字段(8个字节),转为普通的文件名
             如:ABC     MP3 将转为 ABC.MP3

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -