📄 kw_fat32.c
字号:
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 + -