SD_STM32_SPI驱动+FatFs文件系统

来源:互联网 发布:个人网站域名后缀 编辑:程序博客网 时间:2024/06/06 18:42
一.文件列表:MMCSDTimming.pdfSD3.0_20090721.pdf-------详细介绍了SD、SDIO,标准的官方文档SD_FAT文档.docMicrosoft_fat32.doc二、简易FAT32/********************************************************* SD卡,高位在前 SD卡在上电初期,卡主控通过检测引脚1(DAT3)来决定使用SD模式 还是SPI模式。当此脚接50KOhm上拉电阻时,卡进入SD模式; 当此脚为低电平,卡则工作于SPI模式。 *********************************************************/  #include <string.h>     #include "FAT32.h"   #include "stm32f10x_lib.h"   #include "sdcard.h"   //#include"LCM.h"   #define SS       7   #define SS_H    P2OUT |=(1<<SS);   #define SS_L    P2OUT &=~(1<<SS);       unsigned char   SD_SPC; //每簇扇区数(Sectors Per Cluster)   unsigned long   SD_SPF; //每FAT 扇区数(Sectors Per FAT)    unsigned long   SD_ROOT;    //根目录所在扇区(编号为第二簇)   unsigned long   SD_FBG; //FAT表地址   unsigned long   SD_FBG_BOOT;//FAT表基地址       unsigned char   Fat32_DataBuffer[520]={0};      //512+两字节CRC+....   unsigned char   DataBuffer[1024]={0};       //512+两字节CRC+....   unsigned long   FileAddress =0;    /*临时静态变量定义区*/  static  unsigned long Temp0=0;  static  unsigned long Temp1=0;  static  unsigned long Temp2=0;  static  unsigned long Temp3=0;  static  unsigned char StatusInformation ;    void delay(int t)                           //延时   {   int x;   for(;t>0;t--)                               //双重循环    for(x=0;x<1020;x++);  }  /**************************************************** 函数功能:块地址解析 输入: 输出:到指令中间的4个字节中 备注: *****************************************************/  void setblock(unsigned char cmd[],long block)   //获取块地址   {   cmd[1]=block>>15;   cmd[2]=block>>7;     cmd[3]=block<<1;//最低位为0    cmd[4]=0;  }      void Fat32_init(void)//得到SD卡信息:FAT位置,根目录位置,每簇扇区数,每FAT扇区数   {   unsigned char  Fat_Number;     //FAT 数(Number of FAT) 该分区上FAT 的副本数。     #if 0    unsigned char  cmd1[]={0,0,0,0,0,0};//CRC=0x95    unsigned char  dbk;     sdrst();       //SD复位,             CMD0       dbk=1;    cmd1[0]=INIT;    while(dbk)             //等待初始化,   CMD1    {    delay(50);    dbk=SPI_SendCmd(cmd1,0);    usendchar(dbk);   }     cmd1[0]=READ1;     //读BPB,Read Single Block    SPI_SendCmd(cmd1,515);   //usendstr(Fat32_DataBuffer,515);    usendchar(8);   /*  Fat_Number=bp->BPB_NF;      //FAT 数(02)  SD_SPC=bp->BPB_SPC; //每簇扇区数(Sectors Per Cluster)(02)  SD_SPF=bp->BPB_SPF; //每FAT 扇区数(Sectors Per FAT)(000003c3=963)  SD_FBG=bp->BPB_RS;  //保留扇区(0022=34)  SD_ROOT=Fat_Number*SD_SPF+SD_FBG;  *///根目录扇区(编号为第二簇)  #endif    StatusInformation = SD_ReadBlock( 0, (u32 *)Fat32_DataBuffer, 512);  //读取第0扇区      Fat_Number=Fat32_DataBuffer[16];   SD_SPC=Fat32_DataBuffer[13];   SD_SPF=(Fat32_DataBuffer[39]<<24)+(Fat32_DataBuffer[38]<<16)+(Fat32_DataBuffer[37]<<8)+Fat32_DataBuffer[36];   SD_FBG=Fat32_DataBuffer[14]+(Fat32_DataBuffer[15]<<8);   SD_ROOT=Fat_Number*SD_SPF+SD_FBG;   SD_FBG_BOOT=SD_FBG;//保存fat表基地址    //FAT32文件格式: 引导扇区   其余保留扇区   FAT1 FAT2表格(重复的)    根文件夹首簇  其他文件夹及所有文件  剩余扇区   }  /**************************************************** 函数功能:读文件 输入:文件的簇地址 输出: 文件的数据存于全局变量Fat32_DataBuffer[1024]中;若 备注:若成功返回0,表面文件已经结束;若返回1,表明文 件还没有读完,文件的簇地址存在全局变量FileAddress中 *****************************************************/  unsigned char ReadFile(unsigned long cstbg)         //起始簇号   {   unsigned char cmdfo[]={READ1,0,0,0,0,0};   unsigned long cstnxt; //簇       unsigned long adrnxt;                  //扇区    //FAT_FAT *p=(FAT_FAT*)Fat32_DataBuffer;           //FAT表指针       cstnxt=cstbg;                      //得到文件第一个簇       {       adrnxt=SD_SPC*(cstnxt-2)+SD_ROOT;      //减根目录簇号:2                       //读一个簇        #if 0        setblock(cmdfo,adrnxt);                       SPI_SendCmd_2(cmdfo,515,0);       setblock(cmdfo, (adrnxt+1) );        SPI_SendCmd_2(cmdfo,515,1);   #endif        SD_ReadMultiBlocks( (512*adrnxt),(u32 *)DataBuffer,512,2);           /*          for(k=0;k<512;k++)          LCD_WriteData(    *((unsigned int *)Fat32_DataBuffer)  );*/           //usendstr(Fat32_DataBuffer,1023);                               /*                  if( cstnxt==128)          {              SD_FBG +=1;                                      }          if( cstnxt>=128)          {                                    cstnxt -=128;          }          */                                     SD_FBG =SD_FBG_BOOT+cstnxt / (0x80);              cstnxt =cstnxt %(0x80);  #if 0                 setblock(cmdfo,SD_FBG);                //读fat  ????        SPI_SendCmd(cmdfo,515);  #endif        SD_ReadBlock(512*SD_FBG,(u32 *)Fat32_DataBuffer,512);                 //cstnxt=p->FAT_SEC[cstnxt];            //得下一个簇               Temp0=( (unsigned long)(Fat32_DataBuffer[4*cstnxt+3]) )<<8;       Temp0=((unsigned long)(Temp0))<<8;       Temp0=((unsigned long)(Temp0))<<8;       Temp1=( (unsigned long)(Fat32_DataBuffer[4*cstnxt+2]) )<<8;       Temp1=((unsigned long)(Temp1))<<8;            Temp2=( (unsigned long)(Fat32_DataBuffer[4*cstnxt+1]) )<<8;       Temp3=(unsigned long)(Fat32_DataBuffer[4*cstnxt]);       //cstnxt=Fat32_DataBuffer[4*cstnxt]+ (Fat32_DataBuffer[(4*cstnxt)+1]<<8)+(Fat32_DataBuffer[(4*cstnxt)+2]<<16)+(Fat32_DataBuffer[(4*cstnxt)+3]<<24);          cstnxt=Temp3+Temp2+Temp1+Temp0;           FileAddress =cstnxt;       if(cstnxt==0x0fffffff)     //文件结束标志        {              return 0;         }       else       {           return 1;       }   }  }    /**************************************************** 函数功能:在根目录下根据文件存放的序号寻找文件的首簇 输入:    文件的位置序号 输出: (隐形)文件的首簇地址赋值于全局变量FileAddress 备注:若索引成功返回1,失败返回0 *****************************************************/    unsigned char FindFileAdd_AccordingToNum(unsigned char id)          //打开第id个文件   {       unsigned char  i,j=0,k,m,del,atr;//delete,attribute,         unsigned char  flag=0;       unsigned int   t1=0;       unsigned int   t2=0;       unsigned char cmd[]={READ1,0,0,0,0,0};//CRC=0x95          for(m=0;m<200;m++)//xue   该成了从0开始        {           setblock(cmd,SD_ROOT+m);               //读根目录            SPI_SendCmd(cmd,515);           for(i=0;i<16;i++)                   //找到第一个短文件            {                  for(k=0;k<32;k++)                  {                      if(Fat32_DataBuffer[32*i+k])                      break;                  }                  if(k==32)                       return 0;                  del=Fat32_DataBuffer[32*i];                  atr=Fat32_DataBuffer[32*i+11];                  if((del!=0xe5)&&(atr!=0x0f))                      j++;                  if(j==id)                  {                      flag=1;                      break;                  }               }             if(flag)break;       }       if(m==200)return 0;       t1=Fat32_DataBuffer[32*i+20]+ (Fat32_DataBuffer[32*i+21] <<8);        t2=Fat32_DataBuffer[32*i+26]+ (Fat32_DataBuffer[32*i+27] <<8);         FileAddress =t1;       FileAddress=(FileAddress<<16)|t2;       return 1;       //ReadFile(addr);   }      #define SINGLEFILE  0   #define MULTIFILE   1   //要把有关SD卡属性的信息都设成全局变量   /**************************************************** 函数功能:判断两个字符串是否相等 输入:读取的文件名首地址,被核对的文件名首地址 输出: 若相等返回1,否则返回0 备注: *****************************************************/    unsigned char CheckFileName(unsigned char * DiskFileName,unsigned char * CheckedFileName)  {      unsigned char i,j=0;      for(i=0;i<8;i++)      {          if( (*DiskFileName) != (*CheckedFileName) )             {                if( (0x20==*DiskFileName) && (0==*CheckedFileName) )                {                    return 1;                 }                 else                     return 0;            }            DiskFileName++;CheckedFileName++;      }      return 1;  }  /**************************************************** 函数功能:寻找文件的首簇 输入:文件的目录项簇号,文件名,文件类型 输出:文件的首簇地址 备注:若查找失败,返回NULL *****************************************************/  unsigned long FindFileAdd_AccordingToName(unsigned long FileListCluser,unsigned char *FileNameTemp,unsigned char SortTemp)  {   unsigned char  i,j=0,k,m,del,atr;//delete,attribute,     unsigned char  flag=0;   unsigned int   t1=0;   unsigned int   t2=0;   unsigned char cmd[]={READ1,0,0,0,0,0};//CRC=0x95    unsigned long SD_FileCluser=0;   unsigned long addr=0;      SD_FileCluser=SD_SPC*(FileListCluser-2)+SD_ROOT;   for(m=0;m<2;m++)//xue   该成了从0开始,只搜索两个簇    {  #if 0    setblock(cmd,SD_FileCluser+m);             //读文件的目录    SPI_SendCmd(cmd,515);  #endif    SD_ReadBlock( 512*(SD_FileCluser+m) ,(u32 *)Fat32_DataBuffer,512);       for(i=0;i<16;i++)                   //找到第一个短文件        {              for(k=0;k<32;k++)              {                             if(Fat32_DataBuffer[32*i+k])                         break;              }              if(k==32)                   break;     //搜索下一扇区                del=Fat32_DataBuffer[32*i];               atr=Fat32_DataBuffer[32*i+11];               if((del!=0xe5)&&(atr!=0x0f))               {                   //if( CheckFileName( (unsigned char*)(&Fat32_DataBuffer[32*i]),FileNameTemp) )                          if( CheckFileName( &Fat32_DataBuffer[32*i],FileNameTemp) )                         {                              if( (SortTemp==SINGLEFILE) && (Fat32_DataBuffer[32*i+11]!=0x10) )//文档                               {                                  flag=1;                                  break;                              }                              if( (SortTemp==MULTIFILE) && (Fat32_DataBuffer[32*i+11]==0x10) )//文件夹                               {                                  flag=1;                                  break;//;//会跳出包含它的最内层的循环语句(for,while)和switch,而且只跳出一层                                 }                         }               }          }     if(flag)break;   }   if(m==2)return NULL;   t1=Fat32_DataBuffer[32*i+20]+ (Fat32_DataBuffer[32*i+21] <<8);    t2=Fat32_DataBuffer[32*i+26]+ (Fat32_DataBuffer[32*i+27] <<8);      addr=t1;   addr=addr<<16|t2;            //文件起始簇号    /*  FileAddress =t1;  FileAddress=(FileAddress<<16)|t2;*/   return addr;      }    /**************************************************** 函数功能:寻找根目录下文档的首簇 输入:    文件名 输出: (隐形)文件的首簇地址赋值于全局变量FileAddress 备注:若索引成功返回1,失败返回0 *****************************************************/  unsigned char FindSingleFileAdd(unsigned char *FileName)  {       unsigned long FileAddressTemp=0;       FileAddressTemp=FindFileAdd_AccordingToName(2,FileName,SINGLEFILE);       if(NULL==FileAddressTemp)          {              return 0;             }          else          {              FileAddress =FileAddressTemp;//赋给全局变量               return 1;             }  }    /**************************************************** 函数功能:寻找两重文件夹中文档的首簇 输入:    第一个文件夹的名称,第二个文件夹的名称,文档           的名称 输出: (隐形)文件的首簇地址赋值于全局变量FileAddress 备注:若索引成功返回1,失败返回0 *****************************************************/  unsigned char FindMultiFileAdd(unsigned char *FirstFileName,unsigned char *SecondFileName,unsigned char *FileName)  {      unsigned long FileAddressTemp =0;      FileAddressTemp =FindFileAdd_AccordingToName(2,FirstFileName,MULTIFILE);      if(NULL==FileAddressTemp)          return 0;                        //没有找到第一个文件       FileAddressTemp=FindFileAdd_AccordingToName(FileAddressTemp,SecondFileName,MULTIFILE);      if(NULL==FileAddressTemp)          return 0;                        //没有找到第二个文件       FileAddressTemp=FindFileAdd_AccordingToName(FileAddressTemp,FileName,SINGLEFILE);      if(NULL==FileAddressTemp)          return 0;                        //没有找到文件       FileAddress =FileAddressTemp;      ////赋给全局变量       return 1;        }  /*********************************************************SD卡,高位在前SD卡在上电初期,卡主控通过检测引脚1(DAT3)来决定使用SD模式还是SPI模式。当此脚接50KOhm上拉电阻时,卡进入SD模式;当此脚为低电平,卡则工作于SPI模式。*********************************************************/#include <string.h>#include "FAT32.h"#include "stm32f10x_lib.h"#include "sdcard.h"//#include"LCM.h"#define SS       7#define SS_H    P2OUT |=(1<<SS);#define SS_L    P2OUT &=~(1<<SS);unsigned charSD_SPC;//每簇扇区数(Sectors Per Cluster)unsigned longSD_SPF;//每FAT 扇区数(Sectors Per FAT) unsigned longSD_ROOT;//根目录所在扇区(编号为第二簇)unsigned longSD_FBG;//FAT表地址unsigned longSD_FBG_BOOT;//FAT表基地址unsigned charFat32_DataBuffer[520]={0};//512+两字节CRC+....unsigned charDataBuffer[1024]={0};//512+两字节CRC+....unsigned long   FileAddress =0;/*临时静态变量定义区*/static  unsigned long Temp0=0;static  unsigned long Temp1=0;static  unsigned long Temp2=0;static  unsigned long Temp3=0;static  unsigned char StatusInformation ;void delay(int t)//延时{ int x; for(;t>0;t--) //双重循环 for(x=0;x<1020;x++);}/****************************************************函数功能:块地址解析输入:输出:到指令中间的4个字节中备注:*****************************************************/void setblock(unsigned char cmd[],long block)//获取块地址{ cmd[1]=block>>15; cmd[2]=block>>7;   cmd[3]=block<<1;//最低位为0 cmd[4]=0;}void Fat32_init(void)//得到SD卡信息:FAT位置,根目录位置,每簇扇区数,每FAT扇区数{ unsigned charFat_Number;//FAT 数(Number of FAT) 该分区上FAT 的副本数。#if 0 unsigned char cmd1[]={0,0,0,0,0,0};//CRC=0x95 unsigned chardbk; sdrst();//SD复位,             CMD0  dbk=1;  cmd1[0]=INIT;  while(dbk)//等待初始化,   CMD1 {  delay(50);  dbk=SPI_SendCmd(cmd1,0);  usendchar(dbk); } cmd1[0]=READ1;//读BPB,Read Single Block SPI_SendCmd(cmd1,515); //usendstr(Fat32_DataBuffer,515); usendchar(8); /* Fat_Number=bp->BPB_NF;//FAT 数(02) SD_SPC=bp->BPB_SPC;//每簇扇区数(Sectors Per Cluster)(02) SD_SPF=bp->BPB_SPF;//每FAT 扇区数(Sectors Per FAT)(000003c3=963) SD_FBG=bp->BPB_RS;//保留扇区(0022=34) SD_ROOT=Fat_Number*SD_SPF+SD_FBG;*///根目录扇区(编号为第二簇)#endif StatusInformation = SD_ReadBlock( 0, (u32 *)Fat32_DataBuffer, 512);  //读取第0扇区 Fat_Number=Fat32_DataBuffer[16]; SD_SPC=Fat32_DataBuffer[13]; SD_SPF=(Fat32_DataBuffer[39]<<24)+(Fat32_DataBuffer[38]<<16)+(Fat32_DataBuffer[37]<<8)+Fat32_DataBuffer[36]; SD_FBG=Fat32_DataBuffer[14]+(Fat32_DataBuffer[15]<<8); SD_ROOT=Fat_Number*SD_SPF+SD_FBG; SD_FBG_BOOT=SD_FBG;//保存fat表基地址 //FAT32文件格式: 引导扇区   其余保留扇区   FAT1 FAT2表格(重复的)    根文件夹首簇  其他文件夹及所有文件  剩余扇区}/****************************************************函数功能:读文件输入:文件的簇地址输出: 文件的数据存于全局变量Fat32_DataBuffer[1024]中;若备注:若成功返回0,表面文件已经结束;若返回1,表明文件还没有读完,文件的簇地址存在全局变量FileAddress中*****************************************************/unsigned char ReadFile(unsigned long cstbg)//起始簇号{ unsigned char cmdfo[]={READ1,0,0,0,0,0}; unsigned long cstnxt; //簇  unsigned long adrnxt;//扇区 //FAT_FAT *p=(FAT_FAT*)Fat32_DataBuffer;//FAT表指针  cstnxt=cstbg;//得到文件第一个簇  { adrnxt=SD_SPC*(cstnxt-2)+SD_ROOT;//减根目录簇号:2 //读一个簇     #if 0 setblock(cmdfo,adrnxt);                 SPI_SendCmd_2(cmdfo,515,0); setblock(cmdfo, (adrnxt+1) );  SPI_SendCmd_2(cmdfo,515,1); #endif SD_ReadMultiBlocks( (512*adrnxt),(u32 *)DataBuffer,512,2); /* for(k=0;k<512;k++) LCD_WriteData(    *((unsigned int *)Fat32_DataBuffer)  );*/ //usendstr(Fat32_DataBuffer,1023);                          /*                 if( cstnxt==128)         {             SD_FBG +=1;                                   }         if( cstnxt>=128)         {                                   cstnxt -=128;         }         */                           SD_FBG =SD_FBG_BOOT+cstnxt / (0x80);        cstnxt =cstnxt %(0x80);#if 0          setblock(cmdfo,SD_FBG);//读fat  ???? SPI_SendCmd(cmdfo,515);#endif SD_ReadBlock(512*SD_FBG,(u32 *)Fat32_DataBuffer,512);         //cstnxt=p->FAT_SEC[cstnxt];//得下一个簇        Temp0=( (unsigned long)(Fat32_DataBuffer[4*cstnxt+3]) )<<8; Temp0=((unsigned long)(Temp0))<<8; Temp0=((unsigned long)(Temp0))<<8; Temp1=( (unsigned long)(Fat32_DataBuffer[4*cstnxt+2]) )<<8; Temp1=((unsigned long)(Temp1))<<8;      Temp2=( (unsigned long)(Fat32_DataBuffer[4*cstnxt+1]) )<<8; Temp3=(unsigned long)(Fat32_DataBuffer[4*cstnxt]); //cstnxt=Fat32_DataBuffer[4*cstnxt]+ (Fat32_DataBuffer[(4*cstnxt)+1]<<8)+(Fat32_DataBuffer[(4*cstnxt)+2]<<16)+(Fat32_DataBuffer[(4*cstnxt)+3]<<24);   cstnxt=Temp3+Temp2+Temp1+Temp0; FileAddress =cstnxt; if(cstnxt==0x0fffffff)     //文件结束标志 {  return 0; } else { return 1; } }}/****************************************************函数功能:在根目录下根据文件存放的序号寻找文件的首簇输入:    文件的位置序号输出: (隐形)文件的首簇地址赋值于全局变量FileAddress备注:若索引成功返回1,失败返回0*****************************************************/unsigned char FindFileAdd_AccordingToNum(unsigned char id)//打开第id个文件{ unsigned chari,j=0,k,m,del,atr;//delete,attribute,  unsigned charflag=0; unsigned intt1=0; unsigned intt2=0; unsigned char cmd[]={READ1,0,0,0,0,0};//CRC=0x95 for(m=0;m<200;m++)//xue   该成了从0开始 { setblock(cmd,SD_ROOT+m);//读根目录 SPI_SendCmd(cmd,515); for(i=0;i<16;i++)//找到第一个短文件 {     for(k=0;k<32;k++)        {        if(Fat32_DataBuffer[32*i+k])        break;        }        if(k==32)             return 0;        del=Fat32_DataBuffer[32*i];        atr=Fat32_DataBuffer[32*i+11];        if((del!=0xe5)&&(atr!=0x0f))j++;        if(j==id) {    flag=1;    break;}  }  if(flag)break; } if(m==200)return 0; t1=Fat32_DataBuffer[32*i+20]+ (Fat32_DataBuffer[32*i+21] <<8);  t2=Fat32_DataBuffer[32*i+26]+ (Fat32_DataBuffer[32*i+27] <<8); FileAddress =t1; FileAddress=(FileAddress<<16)|t2; return 1; //ReadFile(addr);}#define SINGLEFILE  0#define MULTIFILE   1//要把有关SD卡属性的信息都设成全局变量/****************************************************函数功能:判断两个字符串是否相等输入:读取的文件名首地址,被核对的文件名首地址输出: 若相等返回1,否则返回0备注:*****************************************************/unsigned char CheckFileName(unsigned char * DiskFileName,unsigned char * CheckedFileName){    unsigned char i,j=0;    for(i=0;i<8;i++)    {        if( (*DiskFileName) != (*CheckedFileName) )      {          if( (0x20==*DiskFileName) && (0==*CheckedFileName) )          {              return 1;          }          else             return 0;      }      DiskFileName++;CheckedFileName++;    }    return 1;}/****************************************************函数功能:寻找文件的首簇输入:文件的目录项簇号,文件名,文件类型输出:文件的首簇地址备注:若查找失败,返回NULL*****************************************************/unsigned long FindFileAdd_AccordingToName(unsigned long FileListCluser,unsigned char *FileNameTemp,unsigned char SortTemp){ unsigned chari,j=0,k,m,del,atr;//delete,attribute,  unsigned charflag=0; unsigned intt1=0; unsigned intt2=0; unsigned char cmd[]={READ1,0,0,0,0,0};//CRC=0x95 unsigned long SD_FileCluser=0; unsigned long addr=0;  SD_FileCluser=SD_SPC*(FileListCluser-2)+SD_ROOT; for(m=0;m<2;m++)//xue   该成了从0开始,只搜索两个簇 {#if 0 setblock(cmd,SD_FileCluser+m);//读文件的目录 SPI_SendCmd(cmd,515);#endif SD_ReadBlock( 512*(SD_FileCluser+m) ,(u32 *)Fat32_DataBuffer,512);   for(i=0;i<16;i++)//找到第一个短文件 {        for(k=0;k<32;k++)        {                if(Fat32_DataBuffer[32*i+k])                   break;        }        if(k==32)             break;     //搜索下一扇区         del=Fat32_DataBuffer[32*i];         atr=Fat32_DataBuffer[32*i+11];         if((del!=0xe5)&&(atr!=0x0f))         {             //if( CheckFileName( (unsigned char*)(&Fat32_DataBuffer[32*i]),FileNameTemp) )                   if( CheckFileName( &Fat32_DataBuffer[32*i],FileNameTemp) )               {                        if( (SortTemp==SINGLEFILE) && (Fat32_DataBuffer[32*i+11]!=0x10) )//文档                        {                            flag=1;                            break;                        }                        if( (SortTemp==MULTIFILE) && (Fat32_DataBuffer[32*i+11]==0x10) )//文件夹                        {                            flag=1;                            break;//;//会跳出包含它的最内层的循环语句(for,while)和switch,而且只跳出一层                        }                   }         }  }  if(flag)break; } if(m==2)return NULL; t1=Fat32_DataBuffer[32*i+20]+ (Fat32_DataBuffer[32*i+21] <<8);  t2=Fat32_DataBuffer[32*i+26]+ (Fat32_DataBuffer[32*i+27] <<8);  addr=t1; addr=addr<<16|t2;//文件起始簇号 /* FileAddress =t1; FileAddress=(FileAddress<<16)|t2;*/ return addr;    }/****************************************************函数功能:寻找根目录下文档的首簇输入:    文件名输出: (隐形)文件的首簇地址赋值于全局变量FileAddress备注:若索引成功返回1,失败返回0*****************************************************/unsigned char FindSingleFileAdd(unsigned char *FileName){ unsigned long FileAddressTemp=0; FileAddressTemp=FindFileAdd_AccordingToName(2,FileName,SINGLEFILE); if(NULL==FileAddressTemp) {     return 0; } else {     FileAddress =FileAddressTemp;//赋给全局变量     return 1; }}/****************************************************函数功能:寻找两重文件夹中文档的首簇输入:    第一个文件夹的名称,第二个文件夹的名称,文档          的名称输出: (隐形)文件的首簇地址赋值于全局变量FileAddress备注:若索引成功返回1,失败返回0*****************************************************/unsigned char FindMultiFileAdd(unsigned char *FirstFileName,unsigned char *SecondFileName,unsigned char *FileName){    unsigned long FileAddressTemp =0;    FileAddressTemp =FindFileAdd_AccordingToName(2,FirstFileName,MULTIFILE);    if(NULL==FileAddressTemp)    return 0;                        //没有找到第一个文件    FileAddressTemp=FindFileAdd_AccordingToName(FileAddressTemp,SecondFileName,MULTIFILE);    if(NULL==FileAddressTemp)    return 0;                        //没有找到第二个文件    FileAddressTemp=FindFileAdd_AccordingToName(FileAddressTemp,FileName,SINGLEFILE);    if(NULL==FileAddressTemp)    return 0;                        //没有找到文件    FileAddress =FileAddressTemp;      ////赋给全局变量    return 1;    }FAT32.h[cpp] view plaincopyprint?/**************************** 0x40:复位 0x41:初始化 0x51:读单块 0x58:写单块 0x4a:CID read,16b 0x49:CSD read,16b ****************************/    #define INIT    0X41   #define READ1   0X51   #define WRITE1  0X58   #define RCID    0X4A   #define RCSD    0X49       typedef struct      {       unsigned char BPB_NC1[0x0b];   //无用的        unsigned int  BPB_BPS;         //扇区字节数(Bytes Per Sector)        unsigned char BPB_SPC;         //每簇扇区数(Sectors Per Cluster)        unsigned int  BPB_RS;          //保留扇区数(Reserved Sector)     0x0e        //第一个FAT 开始之前的扇区数,包括引导扇区。本字段的十进制值一般为32        unsigned char BPB_NF;          //FAT 数(Number of FAT) 该分区上FAT 的副本数。   0x0f                               //本字段的值一般为2        unsigned char BPB_NC2[0x0b];   //无用的         //2+2+1+2+2+2+++++        unsigned long  BPB_HS;         //隐藏扇区数(Hidden Sector)该分区上引导扇区        //之前的扇区数。在引导序列计算到根目录的数据区的绝对位移的过程中使用了该值        unsigned long  BPB_LS;         //总扇区数(Large Sector) 本字段包含FAT32 分区中总的扇区        unsigned long  BPB_SPF;        //每FAT 扇区数(Sectors PerFAT)(只被FAT32 使用)该分区   0x1e       //每个FAT 所占的扇区数。计算机利用这个数和 FAT 数以及隐藏扇区数       //(本表中所描述的)来决定根目录从哪里开始。        unsigned int   BPB_EF;         //扩展标志(Extended Flag)(只被FAT32 使用)        unsigned int   BPB_FV;         //文件系统版本(File system Version)只供FAT32 使用,高                               //字节是主要的修订号,而低字节是次要的修订号。        unsigned long  BPB_RCN;        //根目录簇号(Root Cluster Number)        //(只供FAT32 使用) 根目录第一簇的簇号。本字段的值一般为2,但不总是如此        unsigned int   BPB_FSI;        //文件系统信息扇区号(File System Information                               //SectorNumber)(只供FAT32 使用)          unsigned int   BPB_BS;         //备份引导扇区(只供FAT32 使用) 为一个非零值,这个非零                               //值表示该分区保存引导扇区的副本的保留区中的扇区号。         }FAT_BPB;        typedef struct      {       unsigned long FAT_SEC[128];//四字节为一簇       }FAT_FAT;   //文件分配表:file allocation table         typedef struct      {       unsigned char SFILE_NAME1[8];//文件名        unsigned char SFILE_NAME2[3];//扩展名        unsigned char SFILE_ATTR;      //attribute属性        unsigned char SFILE_NEC1;      //系统保留        unsigned char SFILE_DAT1[7];   //日期等        unsigned int  SFILE_ADDH;      //文件起始簇号的高16 位        unsigned char SFILE_DAT2[4];   //日期等        unsigned int  SFILE_ADDL;      //文件起始簇号的低16 位        unsigned long SFILE_LEN;       //表示文件的长度           }FAT_SFILE; //短文件名文件(32)字节         typedef struct      {       unsigned char LFILE_ATTR;      //        unsigned char LFILE_NAME1[10]; //        unsigned char LFILE_NEC1;      //长文件名目录项标志,取值0FH        unsigned char LFILE_NEC2;      //系统保留        unsigned char LFILE_CHK;       //校验值(根据短文件名计算得出)        unsigned char LFILE_LNU1[12];  //长文件名unicode 码        unsigned int  LFILE_ADD;       //文件起始簇号(目前常置0)        unsigned char LFILE_LNU2[4];   //长文件名unicode 码       }FAT_LFILE; //长文件名文件(32)字节         typedef struct      {       FAT_SFILE MENU[16];      }FAT_MENU;          //目录项             // unsigned char FindFileAdd_AccordingToName(unsigned char id);   extern unsigned char ReadFile(unsigned long cstbg);    extern unsigned long FindFileAdd_AccordingToName(unsigned long FileListCluser,unsigned char *FileNameTemp,unsigned char SortTemp);    extern unsigned char FindMultiFileAdd(unsigned char *FirstFileName,unsigned char *SecondFileName,unsigned char *FileName);  extern unsigned char FindFileAdd_AccordingToName_Temp(unsigned char id);    extern  void usendstr(unsigned char s[],unsigned int size);    extern void SdWrite(unsigned char datw[],unsigned long block);//要发送的命令,以及要写在哪一块   extern void delay(int t);        /********************************************************************************************************************* *--------------------------------------2010年4月13日11:22:08   Fat32  外部函数 **********************************************************************************************************************/    extern void Fat32_init(void);  extern unsigned char FindSingleFileAdd(unsigned char *FileName);      extern unsigned char DataBuffer[1024];  extern unsigned long FileAddress;  三、FatFs移植示例。支持格式化文件系统、读写、目录等。目前下面的代码只支持一个设备,如若想支持多个设备的文件系统,比如在SD卡、SPI FLASH中均实现文件系统,改动下面代码即可:对每个Physical drive nmuber响应;底层的驱动只需要提供初始化(包括获取设备的容量)、读写即可。如果希望实现NFS、串口硬盘等,只需要把这几个接口通过通信链路(网络、串口等)映射过去/*-----------------------------------------------------------------------*/  /* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2007        */  /*-----------------------------------------------------------------------*/  /* This is a stub disk I/O module that acts as front end of the existing */  /* disk I/O modules and attach it to FatFs module with common interface. */  /*-----------------------------------------------------------------------*/    #include "diskio.h"   #include "stm32f10x.h"   #include "SD_drive.h"     /*-----------------------------------------------------------------------*/  /* Correspondence between physical drive number and physical drive.      */    #define ATA     0   #define MMC     1   #define USB     2     static int                          bus_in_sdio;      /** * @brief 检查sd卡是否就绪 * @return 0:检测成功 *        -1:检测失败 */  static int check_sdcard(void)  {      return check_maincard();  }      /*-----------------------------------------------------------------------*/  /* Inidialize a Drive                                                    */    DSTATUS disk_initialize (      BYTE drv                /* Physical drive nmuber (0..) */  )  {      if( check_sdcard() == 0 )      {          bus_in_sdio         = 1;          return RES_OK;      }      return RES_ERROR;  }    DSTATUS disk_unmount(BYTE drv)  {      bus_in_sdio         = 0;      return RES_OK;  }      DWORD get_fattime ()  {      return 0;  }  /*-----------------------------------------------------------------------*/  /* Return Disk Status                                                    */    DSTATUS disk_status (      BYTE drv        /* Physical drive nmuber (0..) */  )  {      if(bus_in_sdio == 0)      {          return disk_initialize(drv);      }        //SD_GetStatus(); // == 0 )         //return RES_ERROR;         return RES_OK;  }    /*-----------------------------------------------------------------------*/  /* Read Sector(s)                                                        */    DRESULT disk_read (      BYTE drv,       /* Physical drive nmuber (0..) */      BYTE *buff,     /* Data buffer to store read data */      DWORD sector,   /* Sector address (LBA) */      BYTE count      /* Number of sectors to read (1..255) */  )  {      DRESULT res;      res = (DRESULT)(read_card(sector, count, buff));      if( res != 0 )          return RES_ERROR;      else          return RES_OK;  }        /*-----------------------------------------------------------------------*/  /* Write Sector(s)                                                       */    #if _READONLY == 0   DRESULT disk_write (      BYTE drv,           /* Physical drive nmuber (0..) */      const BYTE *buff,   /* Data to be written */      DWORD sector,       /* Sector address (LBA) */      BYTE count          /* Number of sectors to write (1..255) */  )  {      DRESULT res;      res = (DRESULT)(write_card(sector, count, (unsigned char*)buff));      if( res == 0)          return RES_OK;      else          return RES_ERROR;  }  #endif /* _READONLY */     /*-----------------------------------------------------------------------*/  /* Miscellaneous Functions                                               */  // 返回磁盘状态   DRESULT disk_ioctl (      BYTE drv,       /* Physical drive nmuber (0..) */      BYTE ctrl,      /* Control code */      void *buff      /* Buffer to send/receive control data */  )  {      DRESULT res;      if (drv)      {          return RES_PARERR; //仅支持单磁盘操作,否则返回参数错误       }      //FATFS目前版本仅需处理CTRL_SYNC,GET_SECTOR_COUNT,GET_BLOCK_SIZ三个命令       switch(ctrl)      {      case CTRL_SYNC:                    res = RES_OK;                break;        case GET_BLOCK_SIZE:          *(WORD*)buff = 1;          res = RES_OK;          break;        case GET_SECTOR_COUNT: //读卡容量           *(DWORD*)buff = sd_state.capacity;          break;        default:          res = RES_PARERR;          break;      }      return res;  }  


 

原创粉丝点击