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

📄 fat16.c

📁 在s3c44b0下利用SD卡进行WAV文件(FAT16格式)播放的源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	    hour=rBCDHOUR;
	    min=rBCDMIN;
	    sec=rBCDSEC;

	fatdatetime->Date = ((day << DD_DAY_SHIFT)&DD_DAY_MASK)+((month <<DD_MONTH_SHIFT)&DD_MONTH_MASK)
	        +(((year-1980) <<DD_YEAR_SHIFT)&DD_YEAR_MASK);
	
	fatdatetime->Time = ((hour<<DT_HOURS_SHIFT)&DT_HOURS_MASK)+((min<<DT_MINUTES_SHIFT)&DT_MINUTES_MASK)
	      +(((sec/2)<<DT_2SECONDS_SHIFT)&DT_2SECONDS_MASK);
	
	fatdatetime->TimeTenth = (sec % 2) * 100; //+ systm.wMilliseconds / 10;
}



///////////////////////////////////////////////////////////////////
// fat apis
///////////////////////////////////////////////////////////////////
//创建目录
int fat_mkdir( const char *dirname)//仅1级目录: 父目录\新目录
{
	DIRENTRY dir;
	DWORD SectorNum;
	char path[512];
	char name[11];
	char *p;
	FatDateTime tm;
	_FILE file;	
	BYTE* Cache;
	DIRENTRY *pdir;
	WORD NewCluster;
	char dot[11] = {'.', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
	char dotdot[11] = {'.', '.', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};

	// is path format correct ?
	p = get_valid_format(dirname);
	if(p == NULL)
		return 1;

	//if exist this dir ?寻找是否有相同名字的文件夹/文件
	//若没有,返回0xffffffff。若有,返回扇区数
	if(fat_locate(dirname, NULL) != 0xffffffff)
		return 4;

	//separate path into parent and name(directory name)
	strncpy(name, &p[strlen(p)-11], 11);//拷贝新的目录名->name
    //获得了文件的第一级目录(parent path)名称
	strcpy(path, dirname);
	p = strrchr(path, '\\');//返回path中‘\’第一次出现的指针
	if(p == path) // it is root dir.
		*(p+1) = '\0';
	else
		*p = '\0';
    
	//locate parent path
	SectorNum = fat_locate(path, NULL);//获取第一级目录指向第一个扇区的地址
	if(SectorNum == 0xffffffff)
		return 2;

	//fill dir attributes
	memset((BYTE *)&dir, 0, sizeof(dir));//dir指向的结构体清0
	memcpy((BYTE *)(dir.deName), name, 11);
	dir.deAttributes = ATTR_DIRECTORY;//目录属性0x10:子目录文件
	fat_datetime(&tm);
	dir.CrtDate = dir.LstAccDate = dir.WrtDate = tm.Date;//填写结构体日期
	dir.CrtTime = dir.WrtTime = tm.Time;//填写结构体时间
	dir.CrtTimeTenth = tm.TimeTenth;
	
	//dir.CrtDate = dir.LstAccDate = dir.WrtDate = 0x398b;//填写结构体日期
	//dir.CrtTime = 0x49bd;//填写结构体时间
	//dir.WrtTime = 0x49c0;
	//dir.CrtTimeTenth = 0x8f;
	//dir.deLowerCase  = 0x08;

	//alloc one dir在父目录所指的扇区下获得一个新的目录项
	////从根目录区中取得一个目录项,并将信息写进该目录项,并更新根目录区对应地方数据
	if(AllocDir(SectorNum, &dir, &file) != 0)
		return 3;

	//alloc a cluster 查找空簇,找到后填写0xFFFF,后重写FAT表,返回没用到的空簇
	NewCluster = AllocCluster(0);
	if(NewCluster == 0xffff)
		return 4;

	//flush to disk
	Cache = GetSectorData(file.DirSectorNum);//将新的目录项所在扇区读入
	if(Cache == NULL)						 //用于填写根目录表中的起始簇终止簇
		return 6;

	pdir = (DIRENTRY *)Cache;
	pdir += file.DirIndex;

	pdir->deStartCluster = NewCluster;//填写根目录表中的起始簇终止簇
	Flush();//烧写,内容在SectorBuffer中

	//create . and .. dir items.
	Cache = GetSectorData(ClusterNum2SectorNum(NewCluster));//将新簇的第一个扇区读入
	if(Cache == NULL)										//新簇对应于文件夹对应的数据区
		return 6;
	//填写并烧写文件夹对应数据区的内容
	pdir = (DIRENTRY *)Cache;//获得一个目录项本地目录:.?
	memset((BYTE *)pdir, 0, sizeof(DIRENTRY));
	memcpy((BYTE *)(pdir->deName), dot, 11);
	pdir->deAttributes = ATTR_DIRECTORY;
	fat_datetime(&tm);//获得当前系统的时间,填写当前目录项的属性
	pdir->CrtDate = pdir->LstAccDate = pdir->WrtDate = tm.Date;
	pdir->CrtTime = pdir->WrtTime = tm.Time;
	pdir->CrtTimeTenth = tm.TimeTenth;
	pdir->deStartCluster = NewCluster;//指向本地

	pdir++;//获得一个目录项父目录:..
	memset((BYTE *)pdir, 0, sizeof(DIRENTRY));
	memcpy((BYTE *)(pdir->deName), dotdot, 11);
	pdir->deAttributes = ATTR_DIRECTORY;
	fat_datetime(&tm);
	pdir->CrtDate = pdir->LstAccDate = pdir->WrtDate = tm.Date;
	pdir->CrtTime = pdir->WrtTime = tm.Time;
	pdir->CrtTimeTenth = tm.TimeTenth;
	pdir->deStartCluster = SectorNum2ClusterNum(SectorNum);

	Flush();//烧写,内容在SectorBuffer中

	return 0;
}

//删除目录
int fat_rmdir( const char *dirname)
{
	DWORD SectorNum;
	_FILE file;
	char filename[13];

	//is dir have no sub dir or file ?
	if(fat_getfirst(dirname, filename) == 0)
		return 3;

	//locate
	SectorNum = fat_locate(dirname, &file);
	if(SectorNum == 0xffffffff)
		return 4;

	// is it a dir ?
	if(!(file.dir.deAttributes & ATTR_DIRECTORY))
		return 6;

	if(DeleteDir(&file) != 0)
		return 5;

	FreeCluster(file.dir.deStartCluster);

	return 0;
}

FatGet fat_get;
//path所指目录下是否有子目录或文件,获得第一个子目录/文件名
int fat_getfirst(const char *path, char* filename)
{
	DWORD Sector;
	unsigned int i;
	WORD Cluster;

	//if exist this dir ?
	Sector = fat_locate(path, NULL);
	if(Sector == 0xffffffff)
		return 1;

	if(Sector ==FirstDirSector)
	{
		fat_get.IsRootDir = 1;
		fat_get.DirIndex = 2;

		for(i=0; i<RootDirCount * sizeof(DIRENTRY) / BytesPerSector; i++)
		{
			if(SectorGet(Sector++, &fat_get) == 0)
			{
				strcpy(filename, fat_get.filename);
				return 0;
			}
		}
	}

	else
	{
		fat_get.IsRootDir = 0;
		fat_get.DirIndex = 2;

		Cluster = SectorNum2ClusterNum(Sector);

		// because the sector is the first sector of parent dir,
		// so it is the first sector of cluster.
		/*
		i = (Sector - FirstDataSector) % Bpb.SecPerClus;
		
		if(i != 0)
		{
			for(; i< Bpb.SecPerClus; i++)
			{
				if(SectorGet(Sector++, &fat_get) == 0)
				{
					strcpy(filename, fat_get.filename);
					return 0;
				}
			}

			Cluster = GetNextClusterNum(Cluster);
			Sector = ClusterNum2SectorNum(Cluster);
		}*/
		
		while(Cluster != 0xffff)
		{
			for(i=0; i< SectorsPerCluster; i++)
			{
				if(SectorGet(Sector++, &fat_get) == 0)
				{
					strcpy(filename, fat_get.filename);
					return 0;
				}
			}

			Cluster = GetNextClusterNum(Cluster);
			Sector = ClusterNum2SectorNum(Cluster);
		}
	}

	return 2;
}

int fat_getnext(char* filename)
{
	DWORD Sector;
	unsigned int i;
	WORD Cluster;

	Sector = fat_get.DirSectorNum;

	if(fat_get.IsRootDir)
	{
		i=(Sector - RootDirSectors) * BytesPerSector/ sizeof(DIRENTRY) + fat_get.DirIndex +1;

		for(; i<RootDirCount * sizeof(DIRENTRY) / BytesPerSector; i++)
		{
			if(SectorGet(Sector++, &fat_get) == 0)
			{
				strcpy(filename, fat_get.filename);
				return 0;
			}
		}
	}

	else
	{
		Cluster = SectorNum2ClusterNum(Sector);

		i = (Sector - FirstDataSector) % SectorsPerCluster;

		if(i != 0)
		{
			for(; i< SectorsPerCluster; i++)
			{
				if(SectorGet(Sector++, &fat_get) == 0)
				{
					strcpy(filename, fat_get.filename);
					return 0;
				}
			}

			Cluster = GetNextClusterNum(Cluster);
			Sector = ClusterNum2SectorNum(Cluster);
		}

		while(Cluster != 0xffff)
		{
			for(i=0; i< SectorsPerCluster; i++)
			{
				if(SectorGet(Sector++, &fat_get) == 0)
				{
					strcpy(filename, fat_get.filename);
					return 0;
				}
			}

			Cluster = GetNextClusterNum(Cluster);
			Sector = ClusterNum2SectorNum(Cluster);
		}
	}

	return 2;
}
_FILE handles[16];

int fat_close(int handle)
{
	_FILE *fp;
	FatDateTime tm;
	BYTE* Cache;
	DIRENTRY *dir;

	if(handle <0 || handle >= sizeof(handles)/sizeof(_FILE))
		return -1;

	fp = &handles[handle];

	fat_datetime(&tm);
	fp->dir.LstAccDate = fp->dir.WrtDate = tm.Date;
	fp->dir.WrtTime = tm.Time;

	Cache = GetSectorData(fp->DirSectorNum);
	if(Cache == NULL)
		return -2;

	dir = (DIRENTRY *)Cache;
	dir += fp->DirIndex;

	memcpy((BYTE *)dir, (BYTE *)&fp->dir, sizeof(DIRENTRY));
	Flush();
    FlushFAT();
	handles[handle].valid = 0;
	return 0;
}


//创建文件       	  文件名包括路径     文件属性
int fat_creat(const char* filename, BYTE attribute)
{
	DIRENTRY dir;
	char path[512];
	char name[11];
	char *p;
	DWORD ParentDirSectorNum;
	FatDateTime tm;
	_FILE file;
	DIRENTRY *pdir;
	WORD NewCluster;
	BYTE* Cache;

	//判断文件名包括路径是否有效, is path format correct ?
	p = get_valid_format(filename);
	if(p == NULL)
		return -2;

	//if exist this file ?    寻找是否有相同名字的文件
	//若没有,返回0xffffffff。若有,返回扇区数
	if(fat_locate(filename, NULL) != 0xffffffff)
		return -3;

	//将文件名拷贝到name,不包括路径  separate path into parent and name
	strncpy(name, &p[strlen(p)-11], 11);

	strcpy(path, filename);  //将文件名和路径拷贝到path
	p = strrchr(path, '\\'); //找出path中最后一个\并在该处写0,
	*p = '\0';				 //用于将文件夹和文件名分开

	//locate parent path
	ParentDirSectorNum = fat_locate(path, NULL); //在根目录区寻找是否有与path同名的文件夹
	if(ParentDirSectorNum == 0xffffffff)		 //返回文件夹的第一簇
		return -4;

	//fill dir attributes
	memset((BYTE *)&dir, 0, sizeof(dir));   //dir清0
	memcpy((BYTE *)(dir.deName), name, 11); //将文件名拷贝到dir.deName,不包括路径
	dir.deAttributes = attribute;	//填写属性,0x20代表txt文件
	dir.deLowerCase = 0x00;	//系统保留
	fat_datetime(&tm);				//获取时间,填写时间
	dir.CrtDate = dir.LstAccDate = dir.WrtDate = tm.Date;
	dir.CrtTime = dir.WrtTime = tm.Time;
	dir.CrtTimeTenth = tm.TimeTenth;
	dir.deFileSize = 100;		//文件长度为0

	//alloc one dir	在父目录所指的扇区下获得一个新的目录项
	//从目录区中取得一个目录项,并将信息写进该目录项,并更新根目录区对应地方数据
	//只写了文件名,属性,时间等信息,没有把起始簇信息写入
	if(AllocDir(ParentDirSectorNum, &dir, &file) != 0)
		return -5;

	//alloc a cluster  查找空簇,找到后填写0xFFFF,后重写FAT表,返回没用到的空簇
	NewCluster = AllocCluster(0);
	if(NewCluster == 0xffff)
		return -6;

	//flush to disk
	Cache = GetSectorData(file.DirSectorNum);//取得文件目录区登记该文件信息的扇区的内容
	if(Cache == NULL)
		return -7;

	pdir = (DIRENTRY *)Cache;
	pdir += file.DirIndex;	//加上目录索引,即加上该扇区中第几个目录项

	pdir->deStartCluster= NewCluster;//填写起始簇号
	Flush();//烧写,内容在SectorBuffer中

	return fat_open(filename);
}

long fat_lseek(int handle, long offset, int origin)
{
	_FILE *fp;
	WORD Cluster;
	unsigned int len;
	int i;

	if(handle <0 || handle >= sizeof(handles)/sizeof(_FILE))
		return 0;

	fp = &handles[handle];	//handles为指向_FILE的数组

	switch(origin)
	{
	case SEEK_SET:
		{
			if(offset < 0)
				return (-1);

			fp->offset = offset;
		}
		break;

	case SEEK_CUR:
		{
			if((fp->offset + offset) <0 )
				return (-1);

			fp->offset += offset;
		}
		break;

	case SEEK_END:
		{
			if((fp->offset + offset) <0 )
				return (-1);

			fp->offset = fp->dir.deFileSize + offset;
		}
		break;

	default:
		return (-2);
	}

	// re-locate CurrentSectorNum, SectorOffset
	Cluster = fp->dir.deStartCluster;
	fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster);
	len = 0;

	while(Cluster != 0xffff)
	{
		for(i=0; i< SectorsPerCluster; i++)
		{
			len += BytesPerSector;

			if(len >= fp->offset)
			{
				fp->SectorOffset = fp->offset % BytesPerSector;
				return fp->offset;
			}
			
			fp->CurrentSectorNum ++;
		}

		Cluster = GetNextClusterNum(Cluster);
		fp->CurrentSectorNum = ClusterNum2SectorNum(Cluster);
	}

	return handles[handle].offset;
}

int fat_open(const char* filename)
{
	int i;
	_FILE * fp = NULL;
	DWORD FirstSectorNum;

	for(i=0; i<16; i++)
	{
		if(!handles[i].valid)	//handles为指向_FILE的数组
		{
			fp = &handles[i];
			break;
		}
	}

	if(fp == NULL)
		return -1;

	//寻找是否有相同名字的文件
	//若没有,返回0xffffffff。若有,返回扇区数
	FirstSectorNum = fat_locate(filename, fp);
	if(FirstSectorNum == 0xffffffff)
		return -2;

	fp->StartSectorNum = FirstSectorNum;
	fp->CurrentSectorNum = fp->StartSectorNum;
	fp->SectorOffset = 0;
	fp->offset = 0;
	fp->valid = 1;
	return i;
}

unsigned int fat_read(int handle, void* buffer, unsigned int bytes)
{
	BYTE* Cache;
	unsigned long int read_bytes =0;
	unsigned int max_copy_bytes_in_sector;
	_FILE *fp;
	WORD Cluster;
	int i,j=0;

	if(handle <0 || handle >= sizeof(handles)/sizeof(_FILE))
		return 0;

	fp = &handles[handle];	//装入文件句柄(由之前fat_open带回的x),handles为指向_FILE的数组
	
	//计算要读取的字节数,如果 文件大小 > bytes   bytes就等于它本身
	//					  如果 文件大小 < bytes   bytes就等于文件大小	bytes由实参带入
	bytes = (fp->dir.deFileSize - fp->offset) > bytes ? bytes : (fp->dir.deFileSize - fp->offset);

	Cluster = SectorNum2ClusterNum(fp->CurrentSectorNum);//根据当前扇区算出数据起始簇

	i = (fp->CurrentSectorNum - FirstDataSector) % SectorsPerCluster;//计算是否有不是一整簇的扇区

	if(i != 0)	//读取不满一簇的数据扇区

⌨️ 快捷键说明

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