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

📄 fat16.c

📁 《基于MDK的STM32处理器应用开发》例程,本例程包使用STM32 FirmLibrary V1.0
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Includes ------------------------------------------------------------------*/
#include "config.h"
#include "FAT16.h"

/* Global declare -------------------------------------------------------------*/
typedef __packed struct
{
	u16 ByteOff;
	u16 ClusID;
	u32 SecOff;
	u32 LBA;
	u32 HaveReadByte;
} FATFileIndex;
u8  			SystemID;	   				// 分区类型
u32 			RelativeSectors; 			// 分区起始扇区数,指分区相对于记录该分区的分区表的扇区位置之差 (该分区表:LBA=0x0)。
u32 			TotalSectors;				// 分区总扇区数

u8           	BUFFER[512];      			// 512字节的缓冲区
u16          	ClusterNum;
FATFileIndex    FileIndex;        			// 当前打开的文件
u8          	BPB_SecPerClus;
u16          	BPB_RsvdSecCnt;
u8           	BPB_NumFATs;
u16          	BPB_RootEntCnt;
u16          	BPB_TotSec16;
u16          	BPB_FATSz16;
u32          	BPB_HiddSec;
u16          	BPB_BytesPerSec	;

/* Fuction declare ------------------------------------------------------------*/
void 			ReadBlock (u32 LBA);
u8 				IsEqual (void* A, void* B, u8 Size);
void 			ReadMBR (void);
void 			ReadBPB (void);
u32 			ClusConvLBA (u16 ClusID);
u16 			LBAConvClus(u32 LBA);
u16 			ReadFAT (u16 Index);
void 			GetFileName(u32 secAddr, u16 secNumOff, u8 persecdirOff, u8 filename[], u8 *len);

/* Extern declare -------------------------------------------------------------*/
extern u16 		UnicodeToGB2312(u16 unicode);	// 用二分查找算法
extern u8 		MSD_ReadBlock(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead);

/* Function define ------------------------------------------------------------*/

/*******************************************************************************
* Function Name  : FAT_Init
* Description    : Init the FAT16 File System.
* Input          : Mone
* Output         : None
* Return         : None
*******************************************************************************/
void FAT_Init(void)
{
	ReadMBR();
	ReadBPB();
}

/*******************************************************************************
* Function Name  : ReadBlock
* Description    : Read a block from the sd card
* Input          : LBA--the sd card address
* Output         : None
* Return         : None
*******************************************************************************/
static void ReadBlock(u32 LBA)
{
	MSD_ReadBlock(BUFFER,LBA*512,512);
}

/*******************************************************************************
* Function Name  : IsEqual
* Description    : Compare the two strings
* Input          : A--one string,B--the other string
* Output         : None
* Return         : 0-- not equal, 1--equal
*******************************************************************************/
static u8 IsEqual(void* A, void* B, u8 Size)
{
	u8 i, *a = A, *b = B;
	for(i = 0; i < Size; i++)
		if(a[i] != b[i])
			return 0;
	return 1;
}

/*******************************************************************************
* Function Name  : ReadMBR
* Description    : Read the sd card's first block--MBR
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
static void ReadMBR(void)
{	
	MBR_tag* MBR = (MBR_tag*)BUFFER;
	ReadBlock(0);

	//缓存相关参数
	SystemID		=  MBR->PT[0].SystemID;
	RelativeSectors =  MBR->PT[0].RelativeSectors;
	TotalSectors	=  MBR->PT[0].TotalSectors;
}

/*******************************************************************************
* Function Name  : ReadBPB
* Description    : Read BPB struct
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
static void ReadBPB(void)
{	
	FAT_BPB* BPB = (FAT_BPB*)BUFFER;
	ReadBlock(RelativeSectors);
	//缓存相关参数
	BPB_SecPerClus  =  BPB->BPB_SecPerClus;
	BPB_RsvdSecCnt  =  BPB->BPB_RsvdSecCnt;
	BPB_NumFATs     =  BPB->BPB_NumFATs;
	BPB_RootEntCnt  =  BPB->BPB_RootEntCnt;
	BPB_TotSec16    =  BPB->BPB_TotSec16;
	BPB_FATSz16     =  BPB->BPB_FATSz16;
	BPB_HiddSec     =  BPB->BPB_HiddSec;
	BPB_BytesPerSec =  BPB->BPB_BytesPerSec;
}

/*******************************************************************************
* Function Name  : DirStartSec
* Description    : Get the root directory's sector No.  
* Input          : None
* Output         : None
* Return         : Root directory's sector No. 
*******************************************************************************/
u32 DirStartSec(void)
{
	return RelativeSectors + BPB_RsvdSecCnt + BPB_NumFATs * BPB_FATSz16;
}

/*******************************************************************************
* Function Name  : DataStartSec
* Description    : Get the data area's start sector NO.  
* Input          : None
* Output         : None
* Return         : The data area's start sector NO. 
*******************************************************************************/
static u32 DataStartSec(void)
{
	return DirStartSec() + BPB_RootEntCnt * 32 / 512;
}

/*******************************************************************************
* Function Name  : ClusConvLBA
* Description    : Get one cluster's first sector NO.  
* Input          : The cluster's NO.
* Output         : None
* Return         : The cluster's first sector NO.
*******************************************************************************/
static u32 ClusConvLBA(u16 ClusID)
{
	return DataStartSec() + BPB_SecPerClus * (ClusID - 2);
}

/*******************************************************************************
* Function Name  : LBAConvClus
* Description    : Convert from sector NO. to cluster NO. 
* Input          : The cluster's NO.
* Output         : None
* Return         : The cluster NO.
*******************************************************************************/
static u16 LBAConvClus(u32 LBA)
{
	return (LBA - DataStartSec()) / BPB_SecPerClus + 2;
}

/*******************************************************************************
* Function Name  : ReadFAT
* Description    : Read the value of FAT table 
* Input          : The FAT table's index
* Output         : None
* Return         : The value of assigned FAT index
*******************************************************************************/
static u16 ReadFAT(u16 Index)
{
	u16 *RAM = (u16*)BUFFER;
	ReadBlock(RelativeSectors + BPB_RsvdSecCnt + Index / 256);
	return RAM[Index % 256];
}

/*******************************************************************************
* Function Name  : CalcuFreeSpace
* Description    : Calculate the free space 
* Input          : None
* Output         : None
* Return         : The free space num(in bytes)
*******************************************************************************/
u32 CalcuFreeSpace()
{
    u32 size;
	u16 i, j;
	u16 *RAM = (u16*)BUFFER;
	size = 0;
	//BPB_FATSz16
	for(i = 0 ; i < BPB_FATSz16 ; i++)
	{
	    ReadBlock(RelativeSectors + BPB_RsvdSecCnt + i);
		for(j = 0; j < 256; j++)
		{
		   if(RAM[j] == 0x00)//空闭簇
		      size += BPB_SecPerClus * BPB_BytesPerSec;
		}
	}
	return size;
}

/*******************************************************************************
* Function Name  : GetFileName
* Description    : Get the file name 
* Input          : secAddr--指所要找文件名的首扇区地址
				   secNumOff--指相对首扇区的偏移	
				   persecdirOff--指在扇区内目录项的偏移
				   filename[]--the file name
				   len--the file name length
* Output         : None
* Return         : None
*******************************************************************************/
void GetFileName(u32 secAddr, u16 secNumOff, u8 persecdirOff, u8 filename[], u8 *len)	
{
    u8 i,k;
	DIR *ID;
	u16 tmp ,GB2312;
	signed char j;
	*len = 0;
	if(persecdirOff == 0)	 //当短文件名在扇区的第一目录项时,由于需要以上一目录项来判断是否有长文件名,需要特殊处理
	{
		ReadBlock(secAddr + secNumOff - 1);
		if( BUFFER[15 * 32 + 0xB] == 0x0F) //该文件有长文件名
			persecdirOff = 16;//从上一扇区的最后一个目录项开始读(长文件的目录项是倒放在扇区中)
	    else 
    		ReadBlock(secAddr + secNumOff);//该文件无长名,需要返回原来扇区读短文件名
	}
	if( BUFFER[(persecdirOff - 1) * 32 + 0xB] == 0x0F) //该文件有长文件名
	{
		k = persecdirOff;
		while(1)
		{
	        ID = (DIR*)(&BUFFER[(k - 1) * 32]);

			//从长文件目录项中读取文件名,每个长目录分3个区域存放  
    		for(i = 0x1 ; i <=  0xA; i+=2)
			{
			   tmp = *(((u8 *)ID) + i) + (*(((u8 *)ID) + i + 1) << 8);
			   GB2312 = UnicodeToGB2312(tmp); //将对应的Unicode码转化为GB2312码
	  		   if(((GB2312 & 0xFF00) != 0) && ((GB2312 & 0xFF00) != 0xFF00))//去掉0和FF
    		      filename[(*len)++] = (GB2312 & 0xFF00) >> 8;
    		   if(((GB2312 & 0x00FF) != 0) && ((GB2312 & 0x00FF) != 0x00FF))
    		      filename[(*len)++] = (GB2312 & 0x00FF);
			}
    		for(i = 0xE ; i <=  0x19; i+=2)
			{
			   tmp = *(((u8 *)ID) + i) + (*(((u8 *)ID) + i + 1) << 8);
			   GB2312 = UnicodeToGB2312(tmp); //将对应的Unicode码转化为GB2312码
	  		   if(((GB2312 & 0xFF00) != 0) && ((GB2312 & 0xFF00) != 0xFF00))//去掉0和FF
    		      filename[(*len)++] = (GB2312 & 0xFF00) >> 8;
    		   if(((GB2312 & 0x00FF) != 0) && ((GB2312 & 0x00FF) != 0x00FF))
    		      filename[(*len)++] = (GB2312 & 0x00FF);
			}
            for(i = 0x1C ; i <=  0x1F; i+=2)
			{
			   tmp = *(((u8 *)ID) + i) + (*(((u8 *)ID) + i + 1) << 8);
			   GB2312 = UnicodeToGB2312(tmp); //将对应的Unicode码转化为GB2312码
	  		   if(((GB2312 & 0xFF00) != 0) && ((GB2312 & 0xFF00) != 0xFF00))//去掉0和FF
    		      filename[(*len)++] = (GB2312 & 0xFF00) >> 8;

⌨️ 快捷键说明

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