?? 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 + -