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

📄 fat.c

📁 SD卡简单实现文件系统,是别人发给我的,觉得很有必要放大这里和大家一起共享,希望对你有帮助,谢谢.
💻 C
字号:
#include "FAT.h"
#include "UNICODE.H"

#define MAX_DIR_NU_List 20
static INT8U Get_BPB_Flag =0;

INT8U Data_Buffer[512];
BPB sBPB;
BPB *FAT_BPB;
DIR_LIST Sup_Dir;

struct QueueDL
{
	DIR_LIST Directory_List[MAX_DIR_NU_List];
	INT8U front,rear;
}QU_DIR_List;


void IintQueueDL(struct QueueDL *Q)
{
	Q->front = 0;
	Q->rear = 0;
}

void EnQueueDL(struct QueueDL *Q, DIR_LIST *x)
{//向队列插入元素
	if((Q->rear + 1) % MAX_DIR_NU_List == Q->front)
	{//队列满时将产生覆盖
		Q->front = (Q->front + 1) % MAX_DIR_NU_List; //使队首元素指向下一个位置
	}
	Q->rear = (Q->rear + 1) % MAX_DIR_NU_List;
	Q->Directory_List[Q->rear].FstClu = x->FstClu; 
	Q->Directory_List[Q->rear].FileSize = x->FileSize;
}

DIR_LIST *GetElemQDL(struct QueueDL *Q,INT8U pos)
{//读取POS位置的元素
	if(pos < 1 || pos > MAX_DIR_NU_List)
		return((void *)0);
	return(&Q->Directory_List[(Q->front + pos) % MAX_DIR_NU_List]);
}

BPB *Get_BPB(void)
{
	SD_read_sector(0 , Data_Buffer);
	sBPB.BytsPerSec = ((INT16U)Data_Buffer[OFBPB_BytsPerSec+1] << 8) | Data_Buffer[OFBPB_BytsPerSec];
	sBPB.SecPerClus = Data_Buffer[OFBPB_SecPerClus];
	sBPB.RsvdSecCnt = ((INT16U)Data_Buffer[OFBPB_RsvdSecCnt+1] << 8) | Data_Buffer[OFBPB_RsvdSecCnt];
	sBPB.NumFATs	= Data_Buffer[OFBPB_NumFATs];
	sBPB.RootEntCnt = ((INT16U)Data_Buffer[OFBPB_RootEntCnt+1] << 8) | Data_Buffer[OFBPB_RootEntCnt];
	sBPB.TotSec16	= ((INT16U)Data_Buffer[OFBPB_TotSec16+1] << 8) | Data_Buffer[OFBPB_TotSec16];
	sBPB.FATSz16    = ((INT16U)Data_Buffer[OFBPB_FATSz16+1] << 8) | Data_Buffer[OFBPB_FATSz16];
	sBPB.HiddSec    = ((INT32U)Data_Buffer[OFBPB_HiddSec+3] << 24) | ((INT32U)Data_Buffer[OFBPB_HiddSec+2] << 16) | ((INT32U)Data_Buffer[OFBPB_HiddSec+1] << 8) | Data_Buffer[OFBPB_HiddSec];
	sBPB.TotSec32   = ((INT32U)Data_Buffer[OFBPB_TotSec32+3] << 24) | ((INT32U)Data_Buffer[OFBPB_TotSec32+2] << 16) | ((INT32U)Data_Buffer[OFBPB_TotSec32+1] << 8) | Data_Buffer[OFBPB_TotSec32];
	sBPB.FATSz32    = ((INT32U)Data_Buffer[OFBPB_FATSz32+3] << 24) | ((INT32U)Data_Buffer[OFBPB_FATSz32+2] << 16) | ((INT32U)Data_Buffer[OFBPB_FATSz32+1] << 8) | Data_Buffer[OFBPB_FATSz32];
	sBPB.RootClus   = ((INT32U)Data_Buffer[OFBPB_RootClus+3] << 24) | ((INT32U)Data_Buffer[OFBPB_RootClus+2] << 16) | ((INT32U)Data_Buffer[OFBPB_RootClus+1] << 8) | Data_Buffer[OFBPB_RootClus];
	
	RootDirSectors = ((sBPB.RootEntCnt * 32) + (sBPB.BytsPerSec - 1)) / sBPB.BytsPerSec;
	if(sBPB.FATSz16 != 0)
		FATSize = sBPB.FATSz16;
	else
		FATSize = sBPB.FATSz32;
	FirstDataSector = sBPB.RsvdSecCnt + (sBPB.NumFATs * FATSize) + RootDirSectors;
	if(sBPB.TotSec16 != 0)
		TotSector = sBPB.TotSec16;
	else
		TotSector = sBPB.TotSec32;
	DataSector = TotSector - (sBPB.RsvdSecCnt + (sBPB.NumFATs * FATSize) + RootDirSectors);
	CountOfCluster = DataSector / sBPB.SecPerClus;
	if(CountOfCluster < 4085)
		sBPB.FilSysType = IsFAT12;
	else if(CountOfCluster < 65525)
		sBPB.FilSysType = IsFAT16;
	else 
		sBPB.FilSysType = IsFATA32;
	return(&sBPB);
}	

void Uincode_to_GB(INT16U * x)
{
 	INT16U a,b,c;
 	if(((*x) >= 0x0020) && ((*x) <= 0x007E))
 	{
 		if((*x) >= 'a' && (*x) <= 'z')
 		(*x)-='a'-'A';
 		*x+=0xA380;
 		return;
 	}
 	if((*x)<Unicode[0][0])
 	{
 		*x=0x3F3F;
 		return;
 	}
 	if((*x)>Unicode[UNICODE_MAX-1][0])
 	{
 		*x=0x3F3F;
 		return;
 	}
 	a=0;
 	b=UNICODE_MAX-1;
 	do                  //采用二分查表法,因为该表为顺序表
 	{
   		c=(a+b)/2;
   		if((*x)==Unicode[c][0])
   		{
   			*x=Unicode[c][1];
   			return;
   		}
   		if((*x)<Unicode[c][0])
   		{
   			b=(a+b)/2;
   		}
   		else 
   		{
   			a=(a+b+1)/2;
   		}
 	} while(a!=b);
 	if((*x)==Unicode[a][0])
 	{
 		*x=Unicode[a][1];
 		return;
 	}
 	*x=0x3F3F;  //如果找不到,则显示??
}

void Print_DIR_List(INT16U SecOfDir,INT32U FistDirSecNum)
{
	INT16U i,j,k;
	INT8U Sname[18];
	INT8U temp8u,List_NU=0;
	SDIR sSDIR;
	DIR_LIST DIR_LISTx;
	SDIR *pSD;
	
	pSD = &sSDIR;
	for(i = 0;i < SecOfDir;i++)
	{
		SD_read_sector((FistDirSecNum + i),Data_Buffer);
		for(j=0;j<512;(j+=32))
		{
			pSD->SName[0] = Data_Buffer[j + OFSDIR_SName];
			pSD->SName[1] = Data_Buffer[j + OFSDIR_SName + 1];
			pSD->Attr = Data_Buffer[j + OFSDIR_Attr];
			if(((pSD->Attr & ATTR_LONG_NAME_MASK) != ATTR_LONG_NAME) && (pSD->SName[0] != 0xE5) && (pSD->SName[0] != 0))
			{//找到一个活动的短目录项
				
				if((pSD->Attr & ATTR_VOLUME) == 0)
				{//找到一个文件或子目录
					
					if((pSD->SName[0] != '.') && (pSD->SName[1] != '.'))
					{
						List_NU++;
						for(k=2;k<=10;k++)
						{
							pSD -> SName[k] = Data_Buffer[j + OFSDIR_SName + k];
						}
						if(List_NU/100 != 0)
							Sname[0] = List_NU/100 + 48;
						else
							Sname[0] = ' ';
						temp8u = List_NU%100;
						if(List_NU/10 != 0)
							Sname[1] = temp8u/10 + 48;
						else
							Sname[1] = ' ';
						Sname[2] = temp8u % 10 + 48;
						Sname[3] = '-';
						temp8u=4;
						for(k=0;k<=10;k++)
						{
							if(pSD -> SName[k] != 0x20)
							{
								if(k == 8)
								{
									Sname[temp8u] = '.';
									temp8u++;
								}
								Sname[temp8u] = pSD -> SName[k];
								temp8u++;
							}
						}
						Sname[temp8u] = '\n';
						Sname[temp8u+1] = '\0';
						Sname[16] = '\n';
						Sname[17] = '\0';
						pSD->FstCluH = Data_Buffer[j + OFSDIR_FstCluH + 1]*256 + Data_Buffer[j + OFSDIR_FstCluH];
						pSD->FstCluL = Data_Buffer[j + OFSDIR_FstCluL +1 ]*256+ Data_Buffer[j + OFSDIR_FstCluL];
						pSD->FileSize =  ((INT32U)Data_Buffer[j + OFSDIR_FileSize + 3] << 24) | ((INT32U)Data_Buffer[j + OFSDIR_FileSize + 2] << 16) | ((INT32U)Data_Buffer[j | OFSDIR_FileSize + 1] << 8) | ((INT32U)Data_Buffer[j + OFSDIR_FileSize]);
						DIR_LISTx.FstClu = ((INT32U)pSD -> FstCluH << 16) | pSD -> FstCluL;
						DIR_LISTx.FileSize = pSD->FileSize;
						EnQueueDL(&QU_DIR_List,&DIR_LISTx);
						uar_putchar(Sname);
					}
					else if(pSD->SName[1] == '.')
					{//指向上层目录
						
						pSD->FstCluH = Data_Buffer[j + OFSDIR_FstCluH + 1]*256 + Data_Buffer[j + OFSDIR_FstCluH];
						pSD->FstCluL = Data_Buffer[j + OFSDIR_FstCluL +1 ]*256+ Data_Buffer[j + OFSDIR_FstCluL];
						pSD->FileSize =  ((INT32U)Data_Buffer[j + OFSDIR_FileSize + 3] << 24) | ((INT32U)Data_Buffer[j + OFSDIR_FileSize + 2] << 16) | ((INT32U)Data_Buffer[j | OFSDIR_FileSize + 1] << 8) | ((INT32U)Data_Buffer[j + OFSDIR_FileSize]);
						Sup_Dir.FstClu = ((INT32U)pSD -> FstCluH << 16) | pSD -> FstCluL;
						Sup_Dir.FileSize = pSD->FileSize;
					}
				}
			}
			else if(pSD->SName[0] == 0x00)
			{//此目录为空,并且后续的磁盘空间都为空
				
				i = 0xFFF0;
				break;
			}
		}
	} 
}


void DIR(DIR_LIST *Directory_List)
{
	//INT16U i;
	INT32U	FirstSectorOfCluster;	//给定一个簇号N,该簇的第一个扇区
	INT32U  ThisFATSceNum;			//FAT表中包含该簇号N的扇区号
	INT16U  ThisFATEntOffset;		//该簇号N位于FAT表中FAT项的偏移量	INT32U  FATOffset;
	INT16U  NextCluOfFAT16;
	INT32U  FATOffset;
	
	if(!Get_BPB_Flag)
	{
		FAT_BPB = Get_BPB();
		Get_BPB_Flag = 1;
	}
	
	if((Directory_List == (void *)0) || (Directory_List->FstClu == 0))  
	{//是根目录   
		
		if(FAT_BPB -> FilSysType == IsFAT16)
		{
			FistRootDirSecNum = FAT_BPB->RsvdSecCnt + (FAT_BPB->NumFATs * FAT_BPB->FATSz16);
			Print_DIR_List(RootDirSectors,FistRootDirSecNum);
		}
	}
	else if(Directory_List != (void *)0)
	{
		if(FAT_BPB -> FilSysType == IsFAT16)
		{
			FATOffset = Directory_List->FstClu * 2;
			FirstSectorOfCluster = ((Directory_List->FstClu - 2) * FAT_BPB->SecPerClus) + FirstDataSector;
			do
			{
				ThisFATSceNum = FAT_BPB->RsvdSecCnt + (FATOffset / FAT_BPB->BytsPerSec);
				ThisFATEntOffset = FATOffset % FAT_BPB->BytsPerSec;
				SD_read_sector(ThisFATSceNum,Data_Buffer);
				NextCluOfFAT16 = ((INT16U)Data_Buffer[ThisFATEntOffset + 1] << 8) | Data_Buffer[ThisFATEntOffset];
				FATOffset = NextCluOfFAT16 * 2;
				Print_DIR_List(FAT_BPB->SecPerClus,FirstSectorOfCluster);
				FirstSectorOfCluster = ((NextCluOfFAT16 - 2) * FAT_BPB->SecPerClus) + FirstDataSector;
			} while((NextCluOfFAT16 >= 0x0002) && (NextCluOfFAT16 <= 0xFFEF));
		}
	}
}

void ChDir(INT8U List_NU)
{
	DIR_LIST *Dir_List_Nu;
	if(List_NU == '/')
	{
		IintQueueDL(&QU_DIR_List);
		DIR((void *)0);
	}
	else if(List_NU == '.')
	{
		IintQueueDL(&QU_DIR_List);
		DIR(&Sup_Dir);
	}
	else
	{
		IintQueueDL(&QU_DIR_List);
		Dir_List_Nu = GetElemQDL(&QU_DIR_List,List_NU);
		DIR(Dir_List_Nu);
	}
}

⌨️ 快捷键说明

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