#include "SD.h"
#include "FAT.h"
//FAT系统信息
unsigned long FATOffset; //FAT表的起始绝对扇区号
unsigned long RDTOffset; //RDT表的起始绝对扇区号
unsigned long DataOffset; //Data区的起始绝对扇区号
unsigned int MaxCluster; //最大的簇序号,FAT16
unsigned int RDTEntryNum; //根目录项数
unsigned char ClusterSize; //每簇扇区数
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//将一个16位数按字节倒序
void Swap16(unsigned int *Var)
{
*Var = ((*Var & 0xFF00)>>8 | (*Var & 0x00FF)<<8);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//将一个32位数按字节倒序
void Swap32(unsigned long *Var)
{
*Var = ((*Var & 0xFF000000)>>24 | (*Var & 0x00FF0000)>>8 | (*Var & 0x0000FF00)<<8 | (*Var & 0x000000FF)<<24);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//读取并计算SD卡文件系统信息,返回0x00时操作成功,0xFF时出错。
unsigned char InitFAT()
{ //FAT文件系统参数
unsigned long RelSector;
unsigned long TotalSector;
unsigned int ReservedSector;
unsigned char FATNum;
unsigned int FATSize;
//初始化SD卡
if(InitSD()!=0x00) return 0xFF;
//读取FAT文件系统参数
if(0x00 != ReadSectorPartial(0, 454, 4, (unsigned char *)&RelSector)) return 0xFF;
Swap32(&RelSector);
if(0x00 != ReadSectorPartial(0, 458, 4, (unsigned char *)&TotalSector)) return 0xFF;
Swap32(&TotalSector);
if(0x00 != ReadSectorPartial(RelSector, 14, 2, (unsigned char *)&ReservedSector)) return 0xFF;
Swap16(&ReservedSector);
if(0x00 != ReadSectorPartial(RelSector, 13, 1, &ClusterSize)) return 0xFF;
if(0x00 != ReadSectorPartial(RelSector, 16, 1, &FATNum)) return 0xFF;
if(0x00 != ReadSectorPartial(RelSector, 17, 2, (unsigned char *)&RDTEntryNum)) return 0xFF;
Swap16(&RDTEntryNum);
if(0x00 != ReadSectorPartial(RelSector, 22, 2, (unsigned char *)&FATSize)) return 0xFF;
Swap16(&FATSize);
//计算FAT系统信息
FATOffset = RelSector + ReservedSector;
RDTOffset = FATOffset + FATNum * FATSize;
DataOffset = RDTOffset + (RDTEntryNum * 32) / 512;
MaxCluster = (unsigned int)((TotalSector + 1 - DataOffset) / ClusterSize + 1);
return 0x00; //初始化成功
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//在SD卡根目录下查找指定文件,返回0x00时操作成功,0xFF时出错。
//参数pFile为文件结构体指针;pFileName为要查找的文件名。
//文件名长11字节;前8个为文件名,不足8字节的在后面补空格;后3字节为文件后缀;所有字符为ASCII码大写字符。
unsigned char FileOpen(PFILE pFile, char *pFileName)
{
unsigned int Entry, EntrySecOffset;
unsigned long EntrySector;
unsigned char i;
idata char FileName[11];
for(Entry=0; Entry<RDTEntryNum; Entry++) //在RDT表中搜索各个Entry
{ //计算Entry的起始位置
EntrySector = (Entry * 32) / 512 + RDTOffset;
EntrySecOffset = (Entry * 32) % 512;
//读取Entry的前11字节
if(0x00 != ReadSectorPartial(EntrySector, EntrySecOffset, 11, FileName)) return 0xFF;
//比较文件名
for(i=0; i<11; i++)
{
if(FileName[i] != *(pFileName+i)) break;
}
if(i == 11) break; //文件名匹配,找到文件
}
if(Entry == RDTEntryNum) return 0xFF; //没有找到该文件
//填充FILE结构
if(0x00 != ReadSectorPartial(EntrySector, EntrySecOffset+26, 2, (unsigned char *)&(pFile->FileHead))) return 0xFF;
Swap16(&(pFile->FileHead));
if(0x00 != ReadSectorPartial(EntrySector, EntrySecOffset+28, 4, (unsigned char *)&(pFile->FileSize))) return 0xFF;
Swap32(&(pFile->FileSize));
pFile->CurPos = 0;
return 0x00;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//定位文件当前读写位置,返回0x00时操作成功,0xFF时出错。
//参数pFile为文件结构体指针;Origin为定位参考点;Offset为重定位的偏移量。
unsigned char FileSeek(PFILE pFile, long Offset, unsigned char Origin)
{
long tmp;
switch(Origin)
{
case SEEK_SET : tmp = 0; break;
case SEEK_CUR : tmp = pFile->CurPos; break;
case SEEK_END : tmp = pFile->FileSize; break;
default : return 0xFF;
}
tmp += Offset;
if(tmp < 0 || tmp > pFile->FileSize) return 0xFF;
pFile->CurPos = tmp;
return 0x00;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//读取文件内容,返回0x00时操作成功,0xFF时出错。
//参数pFile为文件结构体指针;pBuf为读取缓冲区;ReadBytes为要读取的字节数。
unsigned char FileRead(PFILE pFile, char *pBuf, unsigned int ReadBytes)
{
unsigned long Sector;
unsigned int Offset;
unsigned int i, Cluster = pFile->FileHead;
if(((pFile->CurPos) + ReadBytes) > (pFile->FileSize)) return 0xFF; //出错,越过文件边界
//计算文件当前读写位置所在的扇区和扇区内偏移量
for(i=0; i < (pFile->CurPos)/(512 * ClusterSize); i++)
{
if(0x00 != ReadSectorPartial((FATOffset + (Cluster / 256)), ((Cluster % 256) * 2), 2, (unsigned char *)&Cluster)) return 0xFF;
Swap16(&Cluster);
if((Cluster > 0xFFF7) && (i < (pFile->CurPos)/(512 * ClusterSize))) return 0xFF; //出错,已到达文件结束扇区
}
Sector = DataOffset + (Cluster - 2) * ClusterSize + ((pFile->CurPos) % (512 * ClusterSize)) / 512;
Offset = (pFile->CurPos) % 512;
//读取文件
while(ReadBytes > 0)
{
if((ReadBytes + Offset) <= 512)
{
if(0x00 != ReadSectorPartial(Sector, Offset, ReadBytes, pBuf)) return 0xFF;
pFile->CurPos += ReadBytes;
ReadBytes = 0;
}
else
{
if(0x00 != ReadSectorPartial(Sector, Offset, (512 - Offset), pBuf)) return 0xFF;
pFile->CurPos += (512 - Offset);
ReadBytes -= (512 - Offset);
}
//跳到下一扇区
if((++Sector - DataOffset) % ClusterSize == 0)
{
if(0x00 != ReadSectorPartial((FATOffset + (Cluster / 256)), ((Cluster % 256) * 2), 2, (unsigned char *)&Cluster)) return 0xFF;
Swap16(&Cluster);
Sector = DataOffset + (Cluster - 2) * ClusterSize;
}
Offset = 0;
}
return 0x00;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//写文件当前位置所在的扇区,返回0x00时操作成功,0xFF时出错。
//参数pFile为文件结构体指针;pBuf为写缓冲区。
//写文件操作以扇区为单位进行,文件当前位置的低9位被忽略;写缓冲区大小为512字节。
//如果只想修改当前扇区的一部分内容,必须将欲修改扇区的内容读到缓冲区,修改后再整扇区回写。
//如果文件长度不是512的整倍数,则在写文件最后一个扇区时将超出文件范围,这种情况下不报错。
//此操作不会修改文件当前位置。
unsigned char FileWrite(PFILE pFile, char *pBuf)
{
unsigned long Sector;
unsigned int i, Cluster = pFile->FileHead;
if((pFile->CurPos / 512) > (pFile->FileSize / 512)) return 0xFF; //出错,越过文件边界
//计算文件当前读写位置所在的扇区
for(i=0; i < (pFile->CurPos)/(512 * ClusterSize); i++)
{
if(0x00 != ReadSectorPartial((FATOffset + (Cluster / 256)), ((Cluster % 256) * 2), 2, (unsigned char *)&Cluster)) return 0xFF;
Swap16(&Cluster);
if((Cluster > MaxCluster) && (i < (pFile->CurPos)/(512 * ClusterSize))) return 0xFF; //出错,越出文件结束扇区
}
Sector = DataOffset + (Cluster - 2) * ClusterSize + ((pFile->CurPos) % (512 * ClusterSize)) / 512;
return WriteSector(Sector, pBuf);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//浏览SD卡根目录(返回根目录下指定的第几个文件的文件名),返回0x00时操作成功,0xFF时出错。
//参数SN指定要查找第几个有效文件;pFileName指向找到的有效文件名。
//文件名长11字节;前8个为文件名,不足8字节的在后面补空格;后3字节为文件后缀;所有字符为ASCII码大写字符。
unsigned char DirBrowse(unsigned char SN, char *pFileName)
{
unsigned int Entry, EntrySecOffset;
unsigned long EntrySector;
for(Entry=0; Entry<RDTEntryNum; Entry++) //在RDT表中搜索各个Entry
{ //计算Entry的起始位置
EntrySector
51单片机读写SD卡程序,使用FAT文件系统
需积分: 40 119 浏览量
2015-09-21
22:40:03
上传
评论 4
收藏 71KB RAR 举报
wangzedu
- 粉丝: 1
- 资源: 4
最新资源
- Screenshot_20240427_031602.jpg
- 网页PDF_2024年04月26日 23-46-14_QQ浏览器网页保存_QQ浏览器转格式(6).docx
- 直接插入排序,冒泡排序,直接选择排序.zip
- 在排序2的基础上,再次对快排进行优化,其次增加快排非递归,归并排序,归并排序非递归版.zip
- 实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip
- 冒泡排序 直接选择排序 直接插入排序 随机快速排序 归并排序 堆排序.zip
- 课设-内部排序算法比较 包括冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、归并排序和堆排序.zip
- Python排序算法.zip
- C语言实现直接插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序、归并排序、计数排序,并带图详解.zip
- 常用工具集参考用于图像等数据处理
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈