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

📄 fat16.c

📁 《基于MDK的STM32处理器应用开发》例程,本例程包使用STM32 FirmLibrary V1.0
💻 C
📖 第 1 页 / 共 2 页
字号:
    		   if(((GB2312 & 0x00FF) != 0) && ((GB2312 & 0x00FF) != 0x00FF))
    		      filename[(*len)++] = (GB2312 & 0x00FF);
			}
			if(k > 0)
			{
				if( ((BUFFER[(k - 1) * 32]) & 0x40) != 0)  //已经到达长文件名的最后一个目录项
				    break;
				k--;	   
			}
			else if(k == 0)	 //该扇区已读完,需要读上一扇区
			{
			    ReadBlock(secAddr + secNumOff - 1);
				k = 16;//从上一扇区的最后一个目录项开始读(长文件的目录项是倒放在扇区中)
			}
		}
	}	
	else //无长文件名
	{
        ID = (DIR*)(&BUFFER[persecdirOff * 32]);
		j = 7;
		while( ID->FileName[j--] == 0x20);
		j++;
	 	while(j >= 0)
		{	   
		   filename[j] = ID->FileName[j];
		   (*len)++;
		   j--;
		}
		j = 10;
		while( ID->FileName[j--] == 0x20);
		j++;		    
		if(j >= 8)//有扩展名,记录下来
		{
		   filename[(*len)++] = '.';
	       if(ID->FileName[8] != 0x20)
    		   filename[(*len)++] = ID->FileName[8]; 
		   if(ID->FileName[9] != 0x20)
	    	   filename[(*len)++] = ID->FileName[9]; 
		   if(ID->FileName[10] != 0x20)
	    	   filename[(*len)++] = ID->FileName[10];
		}
	}
	ReadBlock(secAddr + secNumOff);	 //由于这里BUFFER的内容可能有变化,因此在返回时应复原
}

/*******************************************************************************
* Function Name  : List_DateAndTime
* Description    : List the file's date and time 
* Input          : ID-- director items
* Output         : None
* Return         : None
*******************************************************************************/
void List_DateAndTime(DIR * ID)	
{
    u8 month = 0, date = 0, hour = 0 , minite = 0, second = 0;
	u16 tmp = 0 , year = 0;
   	//获取日期
   	tmp = ID->FileUpdateData[0] + (ID->FileUpdateData[1] <<8);
   	year = ((tmp & 0xFE00) >>9) + 1980;
   	month = (tmp & 0x01E0) >>5;
   	date = (tmp & 0x001F);
   	printf("%4u-%02u-%02u", year, month, date);
   	//获取时间
   	tmp = ID->FileUpdateTime[0] + (ID->FileUpdateTime[1] <<8) ;
   	hour = (tmp & 0xF800) >>11;
   	minite = (tmp & 0x07E0) >>5;
   	second = (tmp & 0x001F) * 2;
   	printf("   %02u:%02u:%02u", hour, minite, second);
	if(ID->FileAttrib & 0x10)//子目录
    	printf("    <DIR>     ");
	else //文件
		printf("              ");
}

/*******************************************************************************
* Function Name  : SearchFoler
* Description    : 在指定扇区(首扇区地址为dirAddr)的所有目录项中查找子目录或文件 
* Input          : dirAddr--首扇区地址
				   foldername--目录或文件名
				   namelen--目录或文件名长度
				   type--1:表示找到文件,0:表示找到子目录
* Output         : None
* Return         : 子目录或文件的首扇区号
*******************************************************************************/

u32 SearchFoler(u32 dirAddr, u8 foldername[], u8 namelen, u8 type)
{  
    u16 cluster ;
    u32 i;//totalSec, i;
    u8 m ;
	DIR *ID;
	u8 filename[256];
	u8 len ;
    if(namelen == 0)
	   return 0;
	cluster = LBAConvClus(dirAddr);	//将扇区号转化为簇号
	while(1)
	{ //这里一个目录如果占用的空间不只一个簇,也可以解决
    	dirAddr = ClusConvLBA(cluster);	//将簇号转为扇区号
      	for(i = 0; i < BPB_SecPerClus; i++)
    	{
    	    ReadBlock(dirAddr + i);	
    		for(m = 0; m < 16; m++)
    		{
    		    if(BUFFER[m * 32] != 0x00 && BUFFER[m * 32] != 0xE5  && BUFFER[m * 32 + 0xB] != 0x0F && (BUFFER[m * 32 + 0xB] & 0x10 ) && type)  
    			//该项为子目录名
     			{
     				ID = (DIR*)(&BUFFER[m * 32]);
    				GetFileName(dirAddr, i, m, filename, &len);
    				if(len != namelen) //两个文件名长度不等,直接跳过
    				    continue;
    				if(IsEqual(foldername, filename, len))//文件名相等,读取其首扇区号
    				{
    				    cluster = BUFFER[m * 32 + 0x1A] + (BUFFER[m * 32 + 0x1B] << 8);//首族号
    					if(cluster == 0)
    	    			   return  ClusConvLBA(1) ;	  //到达根目录,转化为扇区并返回
    			 		else
    	    			   return ( ClusConvLBA(cluster))	;  //将族号转化为扇区号并返回
    		 		}
    			}
    		    else if(BUFFER[m * 32] != 0x00 && BUFFER[m * 32] != 0xE5  && BUFFER[m * 32 + 0xB] != 0x0F && (!(BUFFER[m * 32 + 0xB] & 0x10 )) && (!type))  
    			//该项为文件名
     			{
     				ID = (DIR*)(&BUFFER[m * 32]);
    				GetFileName(dirAddr, i, m, filename, &len);
    				if(len != namelen) //两个文件名长度不等,直接跳过
    				    continue;
    				if(IsEqual(foldername, filename, len))//文件名相等,读取其首扇区号
    				{
    				    cluster = BUFFER[m * 32 + 0x1A] + (BUFFER[m * 32 + 0x1B] << 8);//首族号
                        FAT_FileOpen(ClusConvLBA(cluster));//初始化FATFileIndex结构
						 //返回文件长度
						return (  BUFFER[m * 32 + 0x1c]+ (BUFFER[m * 32 + 0x1c + 1] << 8) + (BUFFER[m * 32 + 0x1c + 2]<< 16)  + (BUFFER[m * 32 + 0x1c + 3]<< 24))	; 
    		 		}
    			}				
    		}
    	}
		cluster = ReadFAT(cluster);
        if(cluster != 0x00 && cluster < 0xFFF0);  //有下一个簇
        else if( cluster <= 0xFFFF && cluster >= 0xFFF8) //最后一个簇
            break;
		else if (cluster  <= 0xFFF7 && cluster >= 0xFFF0) //坏簇或保留值
		    return 0;
	}
	return 0;
}

/*******************************************************************************
* Function Name  : List_AllDir_Long
* Description    : 列出指定扇区和长度(以扇区为单位)的所有目录信息 
* Input          : dirAddr--首扇区地址
* Output         : None
* Return         : None
*******************************************************************************/
//列出指定扇区和长度(以扇区为单位)的所有目录信息,dirAddr为扇区地址
void List_AllDir_Long(u32 dirAddr)
{
    u16 i, m;
	DIR *ID;
	u8 tmp;
	u8 filename[256];
	u8 len;
    u16 cluster ;
	cluster = LBAConvClus(dirAddr);	//将扇区号转化为簇号
	while(1)
	{ //这里一个目录如果占用的空间不只一个簇,也可以解决
		dirAddr = ClusConvLBA(cluster);	//将簇号转为扇区号
		for(i = 0; i < BPB_SecPerClus; i++)
		{
		    ReadBlock(dirAddr + i);	
			for(m = 0; m < 16; m++)
			{
			    if(BUFFER[m * 32] != 0x00 && BUFFER[m * 32] != 0xE5  && BUFFER[m * 32 + 0xB] != 0x0F)
				{
      	  	        if((dirAddr + i * BPB_BytesPerSec ) ==  DirStartSec() && m == 0) //根目录项,区别对待
					//这里存放的是卷号
					{
					    printf("Driver Name Is: ");
						GetFileName(dirAddr, i, m, filename, &len);
					    for(tmp = 0; tmp < len; tmp++)
    					    printf("%c",filename[tmp]);
		   		 		printf("\r\n");
						continue;
					}

					ID = (DIR*)(&BUFFER[m * 32]);
				    List_DateAndTime(ID);
					GetFileName(dirAddr, i, m, filename, &len);
					for(tmp = 0; tmp < len; tmp++)
					    printf("%c",filename[tmp]);
					printf("\r\n");
				}
			}
		}
		cluster = ReadFAT(cluster);
		if(cluster != 0x00 && cluster < 0xFFF0);  //有下一个簇
        else if( cluster <= 0xFFFF && cluster >= 0xFFF8) //最后一个簇
            break;
		else if (cluster  <= 0xFFF7 && cluster >= 0xFFF0) //坏簇或保留值
		    break;
	}
}

/*******************************************************************************
* Function Name  : FAT_FileOpen
* Description    : Open the file 
* Input          : firstSec--首扇区地址
* Output         : None
* Return         : None
*******************************************************************************/
void FAT_FileOpen(u32 firstSec)
{
	FileIndex.HaveReadByte = 0;
	FileIndex.ClusID = LBAConvClus(firstSec);
}

/*******************************************************************************
* Function Name  : FAT_FileRead
* Description    : Read the file content 
* Input          : start--the file offset
				   length--the length to read
				   buff--save the read content
* Output         : None
* Return         : None
*******************************************************************************/
//读取文件的数据
void FAT_FileRead(u32 start,u32 length, u8* buff)
{
	u16 BytePerClus;//, ClusNum;
	u8 *data = buff;
	BytePerClus = BPB_SecPerClus * 512; // 每簇的字节数

    if(length == 0)
	    return;	

	FileIndex.SecOff = (start % BytePerClus) / 512; //开始位置所在扇区簇内偏移
	FileIndex.ByteOff = (start % BytePerClus) % 512; //开始位置扇区内偏移

	FileIndex.LBA = ClusConvLBA(FileIndex.ClusID) + FileIndex.SecOff; //开始位置所在的扇区号
	
	ReadBlock(FileIndex.LBA); //预读取一个扇区的内容

	goto FAT_FileRead_Start;

	while(1)
	{ 
		while(FileIndex.SecOff < BPB_SecPerClus)
		{
			ReadBlock(FileIndex.LBA);
			FileIndex.ByteOff = 0;
FAT_FileRead_Start:
			while(FileIndex.ByteOff < 512)
			{
				*data++ = BUFFER[FileIndex.ByteOff];
				FileIndex.ByteOff++;
				FileIndex.HaveReadByte++;
	 		    if(FileIndex.HaveReadByte % BytePerClus == 0)
        	    {
            		FileIndex.ClusID = ReadFAT(FileIndex.ClusID); //下一簇簇号
            		FileIndex.LBA = ClusConvLBA(FileIndex.ClusID);
            		FileIndex.SecOff = 0;
        		}
				//如果读取完成就退出
				if(--length == 0)
				   return;
			}
			FileIndex.LBA++;
			FileIndex.SecOff++;
		}
	}
}

⌨️ 快捷键说明

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