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

📄 kw_fat32.c

📁 linux下数据下载器的设计与实现
💻 C
📖 第 1 页 / 共 2 页
字号:
				pDir->FileName[0] = 0xe5;								//置删除标志
				j = (pDir->StartClus[0]) | (pDir->StartClus[1] << 8);	//说去首簇
				NM_WritePages(FM_ptr_root + i);							//回写
				if(j != 0)
					FM_DeleteCluLink(j);								//删除簇链
				return 1;
			}
		    pDir ++;
		}
	}
	return 0;
}

/************************************************************************************* 
  Function:       FM_WriteData2Clu
  Description:    写数据到簇中
  Called By:      
  Input:          Clu@WORD:簇号
  				  pBuffer@BYTE *:数据
				  Length@WORD:数据长度
				  Start@WORD: 起始偏移
  Output:         N/A
  Return:         1:成功,0:失败
  Others:         
*************************************************************************************/
bit FM_WriteData2Clu(WORD Clu, BYTE * pBuffer, WORD Length,WORD Start)
{
	xdata WORD tmp;
	xdata DWORD fp_start_sector;

	if((Start + Length) > FM_sectors_clus * 512)					//如果当前簇不够则返回
	{
		return 0;
	}

	fp_start_sector = (Clu-2) * FM_sectors_clus + FM_ptr_data;		//计算开始扇区	
	fp_start_sector += Start/512;									//加上偏移量所占扇区

	Start = Start - Start/512*512;									//计算扇区内偏移
	tmp = 512 - Start;												//当前扇区剩余量
	
	while(Length)
	{
		if(Start != 0)												//如果不是从扇区起始开始写
		{
			NM_ReadPage(fp_start_sector);							//则需要读当前扇区
		}

		if(Length > tmp)											//如果当前扇区不足写下所有数据
		{
			NM_WritePagesFromBuff(fp_start_sector,pBuffer,Start,tmp);
			pBuffer += tmp;											//则写满当前扇区
			Length -= tmp;
		}
		else
		{															//否则写全部数据并可以返回
			NM_WritePagesFromBuff(fp_start_sector,pBuffer,Start,Length);
			pBuffer += tmp;
			Length = 0;
		}

		fp_start_sector ++;											//获取下一扇区
		tmp = 512;													//设置下一扇区剩余空间为512
		Start = 0;													//设置下一扇区起始偏移为0
	}
	return 1;
}

/************************************************************************************* 
  Function:       FM_SetNextClu
  Description:    设置当前簇的下簇地址,用于建立簇链
  Called By:      
  Input:          Current@WORD:当前簇号
				  Next@WORD:下一簇号
  Output:         N/A
  Return:         1:成功,0:失败
  Others:         
*************************************************************************************/
bit FM_SetNextClu(WORD Current, WORD Next)
{
	WORD xdata * pTmp;

	NM_ReadPage(FM_ptr_fats+((Current>>8)&0xff));					//读取当前簇
	pTmp = (WORD *)EP6FIFOBUF;
	pTmp[Current&0xff] = ((Next>>8)&0xff) | ((Next&0xff)<<8);		//设置下簇
	NM_WritePages(FM_ptr_fats+((Current>>8)&0xff));					//回写
	return 1;
}

/************************************************************************************* 
  Function:       FM_WriteFile
  Description:    写数据到当前已打开的文件中,追加方式
  Called By:      
  Input:          Buffer@BYTE*:数据
				  Length@WORD:长度
  Output:         N/A
  Return:         1:成功,0:失败
  Others:         
*************************************************************************************/
bit FM_WriteFile(BYTE * Buffer, WORD Length)
{
	DWORD xdata i;
	WORD xdata tmpClu,Start,tmp;
	WORD xdata LastClu = 0; 
	if(FM_CurrentDirLBA == 0 || FM_pCurrentDir == 0)				//如果当前打开文件不存在则返回
	{
		return 0;
	}

	NM_ReadPage(FM_CurrentDirLBA);									//读取文件目录,并获取文件长度
	((BYTE *)&FM_CurrentFileLength)[0] = FM_pCurrentDir->FileLength[3];
	((BYTE *)&FM_CurrentFileLength)[1] = FM_pCurrentDir->FileLength[2];
	((BYTE *)&FM_CurrentFileLength)[2] = FM_pCurrentDir->FileLength[1];
	((BYTE *)&FM_CurrentFileLength)[3] = FM_pCurrentDir->FileLength[0];	
	
	((BYTE *)&LastClu)[0] = FM_pCurrentDir->StartClus[1];			//获取首簇
	((BYTE *)&LastClu)[1] = FM_pCurrentDir->StartClus[0];


	//计算簇链尾
	for(i = 0; i<(FM_CurrentFileLength/(FM_sectors_clus * 512)); i++)
	{
		tmpClu = FM_GetNextClus(LastClu);
		if(tmpClu == 0xffff)
			break;
		LastClu = tmpClu;
	}


	if(tmpClu == 0xffff && Length > 0)								//文件长度有效且末簇地址无效
	{
		tmpClu = FM_GetFreeClu();									//这种情况较特殊,可能由于文件系统错误引起
		while(tmpClu == 0  || tmpClu > 0xf900)						//需要重新分配簇
		{
			FM_DeleteFirstFile();
			tmpClu = FM_GetFreeClu();
		}

		FM_SetNextClu(LastClu, tmpClu);
		LastClu = tmpClu;
	}


	//计算末簇已使用字节数Start,以及剩余数tmp
	Start = FM_CurrentFileLength - FM_CurrentFileLength/(FM_sectors_clus * 512)*(FM_sectors_clus * 512);
	tmp = FM_sectors_clus * 512 - Start;


	while(Length)
	{
		if(tmp < Length)											//如果剩余数不足写完不数据
		{
			if(tmp != 0)											//如果剩余数不为零则满当前簇
			{
				FM_WriteData2Clu(LastClu, Buffer, tmp, Start);		
			}
			//Set Clu link
			tmpClu = FM_GetFreeClu();								//分配心簇
			
		    while(tmpClu == 0  || tmpClu > 0xf900)					//当分配失败时删除文件
			{
				FM_DeleteFirstFile();
				tmpClu = FM_GetFreeClu();
			}

			if(tmp == Length) 										//如果当前簇足以写入全部数据
				FM_SetNextClu(LastClu, 0xffff);						//则关闭促链
			else
			{
				FM_SetNextClu(LastClu, tmpClu);						//否则增加一个簇到链尾
				LastClu = tmpClu;
			}

			FM_CurrentFileLength += tmp;							//设置文件大小
			Buffer += tmp;											//设置数据缓冲首地址
			Length -= tmp;											//设置剩余量
			tmp = FM_sectors_clus * 512;							//设置下簇容量
			Start = 0;												//设置下簇起始偏移
		 }
		 else
		 {
			FM_WriteData2Clu(LastClu, Buffer, Length, Start);		//当前簇可以写完所有数据
			FM_CurrentFileLength += Length;							//写数据
			break;
		 }			
	}
	
	//close file
	NM_ReadPage(FM_CurrentDirLBA);									//回写文件目录,保存文件长度
	FM_pCurrentDir->FileLength[0] = ((BYTE *)&FM_CurrentFileLength)[3];
	FM_pCurrentDir->FileLength[1] = ((BYTE *)&FM_CurrentFileLength)[2];
	FM_pCurrentDir->FileLength[2] = ((BYTE *)&FM_CurrentFileLength)[1];
	FM_pCurrentDir->FileLength[3] = ((BYTE *)&FM_CurrentFileLength)[0];	
	NM_WritePages(FM_CurrentDirLBA);
}


/************************************************************************************* 
  Function:       FM_GetLastFileNameBySN
  Description:    按文件编号排序,获取最后一个文件名
  Called By:      
  Input:          N/A
  Output:         N/A
  Return:         void
  Others:      	  获取的文件名存放在全局变量   FM_FileName
*************************************************************************************/
void FM_GetLastFileNameBySN()
{
	WORD xdata i,j,k;
	DWORD xdata tmpLBA = 0;
	Dir_tag xdata * pDir = 0;

	//设置文件前缀
	SM_CpyString(FM_FileName,CM_ConfigParameter.File_Start,CM_ConfigParameter.File_StartLength);
	
	for(i=CM_ConfigParameter.File_StartLength;i<8;i++)			//设置文件后缀,字符为'0'
	{
		FM_FileName[i] = '0';
	}
	k = CM_ConfigParameter.File_StartLength+1;

	for(i=0; i<((32 * FM_dirs_fat) / 512); i++)					//打开目录表,开始查找文件并排序
	{
		NM_ReadPage(FM_ptr_root + i);
		pDir = ((Dir_tag * ) (& EP6FIFOBUF[0]));

		for(j=0;j<16;j++)
		{
			//跳过已删除项及空项
			if(pDir->FileName[0] == 0x00 ||  pDir->FileName[0] == 0xe5)	//FileName[0]
			{
				pDir ++;
				continue;
			}

			//调过目录项
			if(pDir->attribute & 0x18)
			{
				pDir ++;
				continue;
			}
			
			//比较文件前缀,若相同
			if(SM_CmpString(pDir->FileName,FM_FileName,CM_ConfigParameter.File_StartLength) == 1)
			{
				//比较后缀,若大于,则复制新名称,即每次比较,找出最大的文件名(ASIIC排序)
				if(SM_CmpString2(FM_FileName,pDir->FileName,8-CM_ConfigParameter.File_StartLength,CM_ConfigParameter.File_StartLength) == 1)
				{
					SM_CpyString(FM_FileName+CM_ConfigParameter.File_StartLength,
						pDir->FileName+CM_ConfigParameter.File_StartLength,8-CM_ConfigParameter.File_StartLength);
				}
			}

		    pDir ++;
		}
	}

	//获取最大文件编号后,再加1,生成新文件名
	for(i=0; i<8;i++)
	{
		if(FM_FileName[8-i-1] >= '9')
			FM_FileName[8-i-1] = '0';
		else
		{
			FM_FileName[8-i-1]++;
			break;
		}
	}
	//生成新扩展名
	FM_FileName[8] = '.';
	SM_CpyString(FM_FileName+9,CM_ConfigParameter.File_Ext,3);
}

/************************************************************************************* 
  Function:       FM_CreateNewFileName
  Description:    创建新文件名
  Called By:      
  Input:          N/A
  Output:         N/A
  Return:         void
  Others:      	  如果按序列号生长文件,文件名在目前目录里已有最大文件名上加1
  				  如果按照日期时间生产,则获取当前时间。×未实现
*************************************************************************************/
void FM_CreateNewFileName()
{
	//if create file by sn;we should get last file
	if(CM_ConfigParameter.File_End == CONFIG_FILE_SN)
	{
		FM_GetLastFileNameBySN();
	}
}

/************************************************************************************* 
  Function:       FM_DeleteFirstFile
  Description:    删除第一个文件
  Called By:      
  Input:          N/A
  Output:         N/A
  Return:         void
  Others:      	  如果有和配置参数文件前缀不同的文件,则优先删除
  				  否则删除序号最小的文件
*************************************************************************************/
void FM_DeleteFirstFile()
{
	FM_GetFirstFileNameBySN();
	FM_DeleteFileInRoot(FM_FileName_F);
}

/************************************************************************************* 
  Function:       FM_GetFirstFileNameBySN
  Description:    获取第一个文件
  Called By:      
  Input:          N/A
  Output:         N/A
  Return:         void
  Others:      	  如果有和配置参数文件前缀不同的文件,返回该文件
  				  否则返回序号最小的文件
*************************************************************************************/
void FM_GetFirstFileNameBySN()
{
	WORD xdata i,j,k;
	DWORD xdata tmpLBA = 0;
	Dir_tag xdata * pDir = 0;

	//获取文件前缀
	SM_CpyString(FM_FileName_F,CM_ConfigParameter.File_Start,CM_ConfigParameter.File_StartLength);

	//设置文件后缀
	for(i=CM_ConfigParameter.File_StartLength;i<8;i++)
		FM_FileName_F[i] = 'Z';
	k = CM_ConfigParameter.File_StartLength+1;

	//开始查找文件并排序
	for(i=0; i<((32 * FM_dirs_fat) / 512); i++)
	{
		NM_ReadPage(FM_ptr_root + i);
		pDir = ((Dir_tag * ) (& EP6FIFOBUF[0]));

		for(j=0;j<16;j++)
		{
			//跳过已删除文件
			if(pDir->FileName[0] == 0x00 ||  pDir->FileName[0] == 0xe5)	//FileName[0]
			{
				pDir ++;
				continue;		
			}

			//跳过目录项
			if(pDir->attribute & 0x18)
			{
				pDir ++;
				continue;
			}
			
			//比较文件前缀
			if(SM_CmpString(pDir->FileName,FM_FileName_F,CM_ConfigParameter.File_StartLength) == 1)
			{
				//若文件前缀相同,则比较是否大于,若不大于则复制文件名
				if(SM_CmpString2(FM_FileName_F,pDir->FileName,8-CM_ConfigParameter.File_StartLength,CM_ConfigParameter.File_StartLength) == 0)
				{
					SM_CpyString(FM_FileName_F+CM_ConfigParameter.File_StartLength,
						pDir->FileName+CM_ConfigParameter.File_StartLength,8-CM_ConfigParameter.File_StartLength);
				}
			}
			else
			{
				//若文件前缀不同,且不是配置文件,则返回
				if(SM_CmpString(pDir->FileName,"KWCONFIG",8) == 0)					
				{
					SM_CpyString(FM_FileName_F,pDir->FileName,8);
					FM_FileName[8] = '.';
					SM_CpyString(FM_FileName_F+9,pDir->ExtName,3);
					return;
				}					
			}
		    pDir ++;
		}
	}
}



⌨️ 快捷键说明

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