📄 fat.c
字号:
//*****************************************************************************
//
// File Name : 'fat.c'
// Title : FAT32 File System
// Author : Andy Zhu - Copyright (C) 2008.7
// Created : 2008.07.20
// Revised : 2008.07.20
// Version : 0.1
// Target MCU : Atmel AVR mega128
//
//*****************************************************************************
#include <avr/io.h>
#include <util/delay.h>
#include "sd.h"
#include "fat.h"
//-----------------------------------------------------------------------------
/******************************************************************************
* 名 称: Look_for_DBR(void)
* 功 能: 根据MBR信息得到启动扇区(DBR)的扇区号
* 参 数: 无
* 返 回 值: 启动扇区(DBR)的扇区号
* 备 注:
*******************************************************************************/
unsigned long int Look_for_DBR(void)
{
unsigned char buffer[512];
unsigned long int DBR_block = 0;
SD_ReadSingleBlock(0,buffer); //read MBR
if ((buffer[510] == 0x55) && (buffer[511] == 0xAA)) //判断是否是有效的扇区
{
/*********read the offset of DBR sector*********/
DBR_block = buffer[0x1c9];
DBR_block <<= 8;
DBR_block |= buffer[0x1c8];
DBR_block <<= 8;
DBR_block |= buffer[0x1c7];
DBR_block <<= 8;
DBR_block |= buffer[0x1c6];
}
else
{
DBR_block = 0;
}
return DBR_block;
}
/******************************************************************************
* 名 称: Get_FAT_BPB_Infor(void)
* 功 能: 读取启动扇区上的相关信息
* 参 数: 无
* 返 回 值: 启动扇区(DBR)的扇区号
* 备 注:
*******************************************************************************/
void Get_FAT_BPB_Infor(void)
{
unsigned char buf[512];
FirstSecNum = Look_for_DBR(); //look for logic block 0
SD_ReadSingleBlock(FirstSecNum,buf); //DBR(DOS BOOT RECORD)
//-----------每扇区字节数,offset 0x0B,一般512字节---
FAT32_BPB_infor.BPB_BytesPerSec = buf[0x0b+1];
FAT32_BPB_infor.BPB_BytesPerSec <<= 8;
FAT32_BPB_infor.BPB_BytesPerSec |= buf[0x0b];
//-----------每簇扇区数,offset 0x0D--------------------
FAT32_BPB_infor.BPB_SecPerClus = buf[0x0d];
//-----------保留扇区数,offset 0x0E----------------
FAT32_BPB_infor.BPB_ResSec = buf[0x0F];
FAT32_BPB_infor.BPB_ResSec <<= 8;
FAT32_BPB_infor.BPB_ResSec |= buf[0x0E];
//-----------该分区上FAT的副本数,offset 0x10-------------------
FAT32_BPB_infor.BPB_NumOfFAT = buf[0x10];
//-----每FAT扇区数(只被FAT32使用)该分区每个FAT所占的扇区数。offset 0x24-----------
FAT32_BPB_infor.BPB_SecPerFAT = buf[0x24+3];
FAT32_BPB_infor.BPB_SecPerFAT <<= 8;
FAT32_BPB_infor.BPB_SecPerFAT |= buf[0x24+2];
FAT32_BPB_infor.BPB_SecPerFAT <<= 8;
FAT32_BPB_infor.BPB_SecPerFAT |= buf[0x24+1];
FAT32_BPB_infor.BPB_SecPerFAT <<= 8;
FAT32_BPB_infor.BPB_SecPerFAT |= buf[0x24];
}
//----------------------------------------------------------------------------
/*****************************************************************************
* 名 称: GetFileInfor(unsigned char *DIR_BUF,DIR_SHORT_STR *pDIR)
* 功 能: 得到短文件名的相关信息
* 参 数: unsigned char *DIR_BUF--->指向短文件32个字节信息首地址的指针
DIR_SHORT_STR *pDIR --->指向目标短文件信息结构的指针
* 返 回 值: 无
* 备 注:
*******************************************************************************/
void GetFileInfor(unsigned char *DIR_BUF,DIR_SHORT_STR *pDIR)
{
unsigned char i;
/*
//----------文件名----offset:0x00---------
for (i=0; i<8; i++)
{
pDIR->DIR_Name[i] = *DIR_BUF++;
}
//----------扩展名----offset:0x08------
for (i=0; i<3; i++)
{
pDIR->DIR_ExtName[i] = *DIR_BUF++;
}
*/
//-------------文件全名-------------------
for (i=0; i<11; i++)
{
pDIR->DIR_FullName[i] = *DIR_BUF++;
}
//----------文件属性---offset:0x0B-----
pDIR->DIR_Attr = *DIR_BUF++;
//----------系统保留----offset:0x0c----
pDIR->DIR_NTRes = *DIR_BUF++;
//-----------创建时间的10毫秒位-----offset:0x0d--------
pDIR->DIR_CrtTimeTenth = *DIR_BUF;
//-----------文件创建时间-----offset:0x0e--------
DIR_BUF += 2;
pDIR->DIR_CrtTime = *DIR_BUF;
pDIR->DIR_CrtTime <<= 8;
DIR_BUF--;
pDIR->DIR_CrtTime |= *DIR_BUF;
//----------文件创建日期-----offset:0x10--------
DIR_BUF += 3;
pDIR->DIR_CrtDate = *DIR_BUF;
pDIR->DIR_CrtDate <<= 8;
DIR_BUF--;
pDIR->DIR_CrtDate |= *DIR_BUF;
//----------文件最后访问日期----offset:0x12---------
DIR_BUF += 3;
pDIR->DIR_LstAccDate = *DIR_BUF;
pDIR->DIR_LstAccDate <<= 8;
DIR_BUF--;
pDIR->DIR_LstAccDate |= *DIR_BUF;
//-----------文件的最近修改时间----offset:0x16-------
DIR_BUF += 5;
pDIR->DIR_WrtTime = *DIR_BUF;
pDIR->DIR_WrtTime <<= 8;
DIR_BUF--;
pDIR->DIR_WrtTime |= *DIR_BUF;
//-----------文件的最近修改日期-----offset:0x18------
DIR_BUF += 3;
pDIR->DIR_WrtDate = *DIR_BUF;
pDIR->DIR_WrtDate <<= 8;
DIR_BUF--;
pDIR->DIR_WrtDate |= *DIR_BUF;
//-----------文件的长度-------offset:0x1C----
DIR_BUF += 7;
pDIR->DIR_FileSize = *DIR_BUF--;
pDIR->DIR_FileSize <<= 8;
pDIR->DIR_FileSize |= *DIR_BUF--;
pDIR->DIR_FileSize <<= 8;
pDIR->DIR_FileSize |= *DIR_BUF--;
pDIR->DIR_FileSize <<= 8;
pDIR->DIR_FileSize |= *DIR_BUF;
//-----------文件起始簇号---offset:0x14 & offset:0x1A--------
DIR_BUF -= 7;
pDIR->DIR_FstClus = *DIR_BUF--;
pDIR->DIR_FstClus <<= 8;
pDIR->DIR_FstClus |= *DIR_BUF;
pDIR->DIR_FstClus <<= 8;
DIR_BUF += 7;
pDIR->DIR_FstClus |= *DIR_BUF--;
pDIR->DIR_FstClus <<= 8;
pDIR->DIR_FstClus |= *DIR_BUF;
}
//--------------------------------------------------
/*****************************************************************************
* 名 称: Calculate_FirstRootDirSecNum
* 功 能: 得到根目录的扇区号
* 参 数:
* 返 回 值: 根目录扇区号
* 备 注:
*******************************************************************************/
unsigned long int Calculate_FirstRootDirSecNum(void)
{
unsigned long int temp;
temp = FirstSecNum + FAT32_BPB_infor.BPB_ResSec + \
FAT32_BPB_infor.BPB_NumOfFAT*FAT32_BPB_infor.BPB_SecPerFAT;
return temp;
}
//--------------------------------------------------
/*****************************************************************************
* 名 称: FAT_Get_File_FirCluNum
* 功 能: 得到指定文件的首簇号
* 参 数: unsigned char *pFileDir--->文件的路径,例如"\\PICTURE\\PIC1.BIN"
DIR_SHORT_STR *pDIR --->指向目标短文件信息结构的指针
* 返 回 值: 目标文件的首簇号
* 备 注:
*******************************************************************************/
unsigned long int FAT_Get_File_FirCluNum( char *pFileDir)
{
volatile unsigned char j,k;
volatile unsigned int s,i;
volatile char *p = pFileDir;
volatile unsigned char depth = 0;
volatile unsigned char Cluster_changed;
unsigned char BUF[512];
char Name_buf[11];
volatile unsigned long int TagFileSec;
FirstRootDirSecNum = Calculate_FirstRootDirSecNum(); //首先指定到根目录下
TagFileSec = FirstRootDirSecNum;
while (*p)
{
if(*p == '\\')
{
depth++;
}
p++;
}
p = pFileDir; //---"\\PICTURE\\PIC1.BIN"
for (j=0; j<depth; j++)
{
p++;
for (i=0; i<11; i++) //---得到整个文件的11字节名称
{
if ((*p == '.')&&(i==8))
{
p++;
i--;
continue; //去除文件的点号
}
if ((*p == '.')&&(i<8))
{
Name_buf[i] = 0X20;
}
else if (*p == '\\')
Name_buf[i] = 0X20;
else if (*p == '\0')
Name_buf[i] = 0X20;
else
Name_buf[i] = *p++;
}
Cluster_changed = 0;
for (k=0; k<FAT32_BPB_infor.BPB_SecPerClus; k++)//在一簇里查找
{
SD_ReadSingleBlock(TagFileSec++,BUF); //读取一个扇区
//---读取一个文件的相关信息------
for (i=0,s=(i<<5); i<16; i++,s=(i<<5)) //16x32=512
{
if (BUF[s] == 0x00) //文件目录结束
return 0; //没有找到文件则返回0
if ((BUF[s] == 0xe5)||(BUF[s] == 0x05))
continue; //文件已经被删除,继续读取下一个文件目录信息
if ((BUF[s+0x0b] == 0x08)||(BUF[s+0x0b] == 0x0f))
continue; //卷名或长文件名
if ((depth == 1)&&(BUF[s+8] == 0x20))
continue; //查找的文件在根目录下,则为目录文件(没有扩展名)的直接放弃
//else if ((depth > 1)&&(BUF[s+8] != 0x20))
// continue; //查找的文件不在根目录下,则根目录下的文件(有扩展名)则放弃
GetFileInfor(&BUF[s],&FAT32_DIR_infor); //读取文件的相关信息
if (FileNameMatch(Name_buf,(char*)FAT32_DIR_infor.DIR_FullName)) //名字匹配
{
if (j == depth-1) //已经是最后层目录
return (FAT32_DIR_infor.DIR_FstClus);
else
{
TagFileSec = (FAT32_DIR_infor.DIR_FstClus - 2)*FAT32_BPB_infor.BPB_SecPerClus+FirstRootDirSecNum;
Cluster_changed = 1;
break;
}
}
}
if (Cluster_changed)
break;
}
}
//--------------------------------------
return 0;
}
//--------------------------------------------------
unsigned char FileNameMatch(char *TagName,char *FileName)
{
unsigned char m;
for (m=0; m<11; m++)
{
if (*(TagName+m)!=*(FileName+m))
return 0; //名字不匹配,返回0
}
return 1; //名字匹配,返回1
}
//--------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -