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

📄 fat.c

📁 用LPC2103(ARM7)操作SD卡代码。
💻 C
字号:
/****************************************Copyright (c)**************************************************
**
**											力天电子
**								     http://www.LT430.com
**作者:何呈 
**文件名称:fat.C
**功能:
**说明:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#include <string.h>
#include "sd.h"
#include "fat.h"
#include "uart.h"

extern uchar BUFFER[512];
BYTE  LONGNAME_BUFFER_ADDR[30];
BYTE  DIRNAME_BUFFER_ADDR[30];
BYTE *LongNameBuffer = (BYTE *) LONGNAME_BUFFER_ADDR;
BYTE *DirNameBuffer = (BYTE *) DIRNAME_BUFFER_ADDR;
BYTE Fat32Enabled;
DWORD FirstDataSector; 	//根目录扇区号
WORD  BytesPerSector;   //每个扇区的自己数
WORD  SectorsPerCluster;//每个簇的扇区数
DWORD FirstFATSector;	//FAT1的扇区
DWORD SecondFATSector;  //FAT2的扇区
DWORD SectorsPerFat;	//每个FAT的扇区
DWORD FirstDirSector;   //
DWORD FileSize;	
DWORD FatInCache = 0;

//********************************************************************************************
//读一个扇区
//********************************************************************************************
void ReadBlock(DWORD LBA)
{   
	DWORD temp;
	temp=LBA<<9;
	SD_Read_Block(temp);
}
/*-----------------------------------------------------------------------
 查询数据区一个簇开始扇区号
-----------------------------------------------------------------------*/
DWORD fatClustToSect(DWORD clust)
{
	return ((clust-2) * SectorsPerCluster) + FirstDataSector;
}
/*-----------------------------------------------------------------------
 查询一个簇所占扇区数
-----------------------------------------------------------------------*/
DWORD fatClusterSize(void)
{
	// return the number of sectors in a disk cluster
	return SectorsPerCluster;
}
/*-----------------------------------------------------------------------
查询SD卡文件系统信息
-----------------------------------------------------------------------*/
BYTE fatInit()
{
    WORD data;BYTE t1,t2;
    struct partrecord PartInfo;
	struct bpb710 *bpb;
	// 读MBR结构,分区表
	ReadBlock(0);
	// 读取分区表信息
	PartInfo = *((struct partrecord *) ((struct partsector *)BUFFER)->psPart);
	//FirstDataSector	= PartInfo.prStartLBA;
	// 读启动扇区,启动扇区号在PartInfo.prStartLBA中
	delay_nus(1000); //延时
	
	ReadBlock(PartInfo.prStartLBA);  //ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
	bpb = (struct bpb710 *) ((struct bootsector710 *) BUFFER)->bsBPB;
	//获取根目录扇区号
	FirstDataSector	= PartInfo.prStartLBA;
	if(bpb->bpbFATsecs)
	{
		// bpbFATsecs非0,为FAT16,FAT表所占的扇区数在bpbFATsecs里
		FirstDataSector	+= bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
	}
	else
	{
		// bpbFATsecs是0,为FAT32,FAT表所占的扇区数在bpbBigFATsecs里
		FirstDataSector	+= bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbBigFATsecs;
	}
	
	SectorsPerCluster	= bpb->bpbSecPerClust;
	SectorsPerFat       = bpb->bpbBigFATsecs;
	BytesPerSector		= bpb->bpbBytesPerSec; 
	FirstFATSector		= bpb->bpbResSectors + PartInfo.prStartLBA;
	SecondFATSector     = FirstFATSector+SectorsPerFat;
	
	
	//查询SD卡文件系统分区类型
	switch (PartInfo.prPartType)
	{
		case PART_TYPE_DOSFAT16:
		case PART_TYPE_FAT16: 
		case PART_TYPE_FAT16LBA:
			// 第一个目录扇区号为2
			FirstDirSector	= CLUST_FIRST;
			//FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
			Fat32Enabled = 0;
			
			break;
		case PART_TYPE_FAT32LBA:
		case PART_TYPE_FAT32:
			
			FirstDirSector = bpb->bpbRootClust;
			Fat32Enabled = 1;
			break;
		default:break;
			//return 1;
	}
	//查询SD卡文件系统信息
	switch (PartInfo.prPartType)
	{
		case PART_TYPE_DOSFAT16:
				UART0_PutString("\tDOSFAT 16\n");
				break;
		case PART_TYPE_FAT16:
				UART0_PutString("\tFAT16 \n");
				break;
		case PART_TYPE_FAT16LBA:
				UART0_PutString("\tFAT16 LBA\n");
				break;
		case PART_TYPE_FAT32LBA:
				UART0_PutString("\tFAT32 LBA\n");
				break;
		case PART_TYPE_FAT32:
				UART0_PutString("\tFAT32\n");
				break;
		default:
				UART0_PutString("\tNo Partition!\n");
				break;
	}

	data=PartInfo.prSize>>11; //获取容量
    //打印版本号
    UART0_PutString("\tFile System Version:");
    UART0_PutString((char *)((struct bootsector710 *) BUFFER)->bsOEMName);	//版本号
    UART0_PutString("\n");
    
    //显示磁盘容量
   // data=PartInfo.prSize>>11;
    //打印磁盘容量大小(单位M)
    UART0_PutString("\tDisk Capacity:");
    t1=data/100;
    UART0_PutChar(t1+48);
    data=data%100;
    t1=data/10;
    UART0_PutChar(t1+48);
    t2=data%10;
    UART0_PutChar(t2+48);
    UART0_PutString("M");
    return 0;
}

/*-----------------------------------------------------------------------
查询一个文件的开始簇
短文件目录用32个字节表示,结构体 direntry。一个Sector 有 512/32=16个 direntry

返回文件开始簇的地址
-------------------------------------------------------------------- ---*/
WORD baseentry = 0;
WORD entrycount = 0;

//将字符串str全部转换成大写。返回指针为str的值
char *strupr(char *str)
{
  U8 i;
  for(i=0;i<strlen(str);i++)
  {
    if(str[i]<='z' && str[i]>='a')
      str[i]-='a'-'A';
  }
  return str;
}
//提出文件的名,和扩展名
void Analysis_filename(char *fn,char *file_N,char *file_T)
{
  U8 i=0,tmp=0;
  
  for(i=0;i<strlen(fn);i++)
  {
    if(fn[i]=='.')
    {
      file_N[i]=0;//字符串结尾
      break;  
    }
    file_N[i]=fn[i];
  }
  i++;
  for(;i<strlen(fn);i++,tmp++)
  {
    file_T[tmp]=fn[i];
  }
  file_T[tmp+1]=0;//字符串结尾
  
  strupr(file_N); //转换成大写
  strupr(file_T); //转换成大写  
}
//检查两个字符串的前n个字符是否相同
char strcmp_n(char *str1,char *str2,U8 n)
{
  U8 i;
  for(i=0;i<n;i++)
  {
    if(str1[i]!=str2[i])
      break;
  }
  if(i==n)
    return 1;
  else
    return 0;
}
DWORD fatGetDirEntry(DWORD entry,char *filename)
{
	DWORD sector;
	struct direntry *de = 0;	// 防止compiler warning
	struct winentry *we;
	WORD hasBuffer;
	WORD b;
	short i,index;
	BYTE *p;
	char file_N[10];
        char file_T[5];
        Analysis_filename(filename,file_N,file_T);  //解析文件名
        
	entrycount = 0;
	DirNameBuffer = 0;
	
	// 读取目录区数据
	sector = fatClustToSect(FirstDirSector);
	
	hasBuffer = 0;

	index = 16;	
	do 
	{
		if(index == 16)	// 是否该一人一扇区time for next sector ?
		{
			ReadBlock(sector++);
			de = (struct direntry *)BUFFER;
			index = 0;
		}
		
		if(*de->deName != 0xE5)
		{
			// 如果if not a deleted entry
			if(de->deAttributes == ATTR_LONG_FILENAME)
			{
				// we have a long name entry
				//长文件名
				we = (struct winentry *) de;
				b = 13 *( (we->weCnt-1) & 0x0f);				// index into string
				p = &LongNameBuffer[b];
				for (i=0;i<5;i++)	*p++ = we->wePart1[i*2];	// copy first part			
				for (i=0;i<6;i++)	*p++ = we->wePart2[i*2];	// second part
				for (i=0;i<2;i++)	*p++ = we->wePart3[i*2];	// and third part
				if (we->weCnt & 0x40) *p = 0;					// in case dirnamelength is multiple of 13
				if ((we->weCnt & 0x0f) == 1) hasBuffer = 1;		// mark that we have a long entry
			}
			else	//短文件名
			{
				// we have a short name entry
				// check if this is the end of a multi-part long name entry
				if(hasBuffer)
				{
					// a long entry name has been collected
					// is it a directory ?
					if(de->deAttributes == ATTR_DIRECTORY)
					{
						DWORD save = FirstDirSector;
						DWORD save2 = baseentry;
						DWORD rval;
						
						strcpy((char *)DirNameBuffer,(char *)LongNameBuffer);
						strcat((char *)DirNameBuffer,"/");

						//rprintfStr(LongNameBuffer); rprintfProgStrM("/"); //EOL();
						// call recursively
						FirstDirSector = ((DWORD)de->deHighClust << 16) + de->deStartCluster;
						rval = fatGetDirEntry(entry,filename);
						FirstDirSector = save;
						baseentry = save2;
						if (rval)
							return rval;
						else	
						{
							// reload original sector
							ReadBlock(sector-1);//ataReadSectors( DRIVE0,	sector-1, 1, SectorBuffer);
							entrycount--;			// decrement entry counter		
							*DirNameBuffer = 0;
                 		}
					}
					else // normal file entry
						if(entrycount == entry)		
							break;
					hasBuffer = 0;	// clear buffer	
					entrycount++;	// increment entry counter		
				}
				// else ignore short_name_only entries
			}
			//if(memcmp((char *)"TXT",(char *)de->deExtension,3)==0) goto SendOut;
			//if((*de->deExtension==0x54) && (*(de->deExtension+1)==0x58) && (*(de->deExtension+1)==0x54)) //是txt文件

                        if(strcmp_n((char*)de->deName,file_N,strlen(file_N)) && strcmp_n((char*)de->deExtension,file_T,strlen(file_T)))                        
                                goto SendOut;
		}
		
		de++;
		index++;
	}while (*de->deName || index == 16);	// 0 in de->deName[0] if no more entries

	if (hasBuffer == 0)		// end of entries
		return 0;

SendOut:
	FileSize = de->deFileSize;
	return (DWORD) ((DWORD)de->deHighClust << 16) + de->deStartCluster;
}

/*-----------------------------------------------------------------------
 在FAT表中查询下一个簇所在扇区号
-----------------------------------------------------------------------*/
DWORD fatNextCluster(DWORD cluster)
{
	DWORD nextCluster;
	DWORD fatMask;
	DWORD fatOffset;
	DWORD sector;
	DWORD offset;
	
	if(Fat32Enabled)
	{
		//一个表项为4bytes(32 bits)
		fatOffset = cluster << 2;
		//设置 FAT32 bit mask
		fatMask = FAT32_MASK;
	}
	else
	{
		//一个表项为2bytes(16 bits)
		fatOffset = cluster << 1;
		//设置 FAT16 bit mask
		fatMask = FAT16_MASK;
	}
	
	//计算FAT扇区号
	sector = FirstFATSector + (fatOffset / BytesPerSector);
	//计算FAT扇区号中表项的偏移地址
	offset = fatOffset % BytesPerSector;
    
	ReadBlock(sector);

	// 读取下一个簇号
	nextCluster = (*((DWORD*) &((char*)BUFFER)[offset])) & fatMask;

	// 是否文件的结束簇
	if (nextCluster == (CLUST_EOFE & fatMask))
		nextCluster = 0;
		
	return nextCluster;
}

⌨️ 快捷键说明

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