找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4009|回复: 3
收起左侧

[原创]开源AVR32从SD卡中用FAT32文件系统读取文本显示于LCD的Proteus仿真源码

[复制链接]
ID:405708 发表于 2018-10-10 19:08 | 显示全部楼层 |阅读模式
这个程序是我8年前无聊时做的,SD卡镜像文件可用uiso打开,编辑后保存镜像文件后可在Proteus中看到效果。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
微信图片_20181009214741.png 0.png

AVR32单片机源程序如下:
  1. /*************************************************************************
  2. *文    件:                fs/fat32.c
  3. *作    用:                SD/MMC卡的相关操作
  4. *作    者:                宋
  5. *************************************************************************/
  6. #include "../config.h"                  //配置文件
  7. #include "../drivers/mmc.h"             //MMC卡驱动
  8. #include "fat32.h"
  9. #include "../gui/font.h"
  10. DBRInfo dbrInfo;
  11. buf_t dataBuffer;
  12. File *fileItem;
  13. LongDir *longItem;
  14. uint8 getFileInfo(void);
  15. uint8 delSpace(buf_t string,buf_t stringd,uint8 len);
  16. uint32 currentPath;     
  17. uint16 currentLong;                     //当前路径所在簇

  18. /*************************************************************************
  19. *函    数:                chedkNameSum
  20. *作    用:                计算短文件名的效验和
  21. *入口参数:                FileName(短文件名)
  22. *返 回 值:            Sum(短文件名的效验和)
  23. *备    注:     这个函数参考了Microsoft Extensible Firmware Initiative FAT32 File System Specification.pdf
  24. *************************************************************************/
  25. uint8 checkNameSum(buf_t FileName)
  26. {
  27.         uint8 FileNameLen;
  28.         uint8 Sum;
  29.         Sum = 0;
  30.         for(FileNameLen = 11;FileNameLen != 0;FileNameLen --)         //共11个字符
  31.         {
  32.                 Sum = ((Sum & 1) ? 0x80 : 0) + (Sum >> 1) + *FileName ++;  //计算效验和
  33.         }
  34.         return Sum;
  35. }

  36. /*************************************************************************
  37. *函    数:                bigToSmallending
  38. *作    用:                大小端转换
  39. *入口参数:                big(大端数据)
  40. *返 回 值:            len(big的长度)
  41. *备    注:     这个函数参考了一个帖子 忘记是哪个帖子了
  42. *************************************************************************/
  43. /*
  44. uint32 bigToSmallEnding(uint32 big,uint8 len)
  45. {
  46.         uint32 result = 0;                              
  47.         uint32 fact = 1;                             
  48.         int8 i;
  49.         for(i = 0;i < len;i ++)
  50.         {
  51.                 result += ((uint8 *)&(big))[i] *fact;        
  52.                 fact *= 0x100;
  53.         }
  54.         return big;
  55. }
  56. */

  57. /*************************************************************************
  58. *函    数:                stringCmp
  59. *作    用:                比较字符串
  60. *入口参数:                str1(字符串1),str2(字符串2),len(长度)
  61. *返 回 值:            0不同 1相同
  62. *************************************************************************/

  63. uint8 stringCmp(buf_t str1,buf_t str2,uint8 len)
  64. {
  65.         uint8 i;
  66.         for(i = 0;i < len; i ++)
  67.         {
  68.                 if(str1[i] != str2[i]) return 0;
  69.         }
  70.         return 1;
  71. }


  72. /*************************************************************************
  73. *函    数:                readSector
  74. *作    用:                读一扇区数据
  75. *入口参数:                add(扇区地址),buf(数据缓冲区)
  76. *返 回 值:            TRUE(成功),FALSE(失败)
  77. *************************************************************************/

  78. uint8 readSector(uint32 add,buf_t buf)
  79. {
  80.         return MMC_ReadSector(add,buf);
  81. }

  82. /*************************************************************************
  83. *函    数:                getDBRInfo
  84. *作    用:                获取FAT的基本信息
  85. *入口参数:                dbrsector(DBR所在的扇区)
  86. *返 回 值:            TRUE(成功),FALSE(失败)
  87. *************************************************************************/
  88. uint8 FAT_Initialize(uint32 dbrSector)
  89. {
  90.         buf_t tmpString = malloc(11);
  91.         dataBuffer = malloc(512);
  92.         FAT32_DBR *dbr          = (FAT32_DBR *)dataBuffer;
  93.         if(readSector(dbrSector,dataBuffer) == FALSE)
  94.         {
  95.                 free(tmpString);
  96.                 free(dataBuffer);
  97.                 return FALSE;
  98.         }
  99.         dbrInfo.bytePerSector   = dbr->BPB_BytsPerSec;                               //每扇区字节数
  100.         dbrInfo.rootDirClust    = dbr->BPB_RootClus;                                                                 //根目录所在簇
  101.         dbrInfo.sectorsPerClust = dbr->BPB_SecPerClus;                               //每簇扇区数
  102.         dbrInfo.FATSector       = dbr->BPB_FATSz32;                                  //FAT表所占扇区数
  103.         dbrInfo.firstFATSector  = dbr->BPB_RsvdSecCnt;                                                                 //第一个FAT表的位置
  104.         dbrInfo.rootDirSector   = dbrInfo.firstFATSector \
  105.                                                                                 +(dbrInfo.FATSector * dbr->BPB_NumFATs); //根目录所在扇区
  106.         currentPath = dbrInfo.rootDirClust;

  107.         free(tmpString);
  108.         free(dataBuffer);
  109.         return TRUE;
  110. }

  111. /*************************************************************************
  112. *函    数:                getNextClust
  113. *作    用:                根据当前簇获取下一簇
  114. *入口参数:                currentClust(当前簇)
  115. *返 回 值:            nextClust(下一簇)
  116. *************************************************************************/

  117. uint32 getNextClust(uint32 currentClust)
  118. {
  119.         uint32 nextClust;                                                  //定义下一个簇
  120.         readSector(
  121.                         dbrInfo.firstFATSector                                                                     //FAT表项的首扇区
  122.                          + (uint32)((currentClust << 2) >> 9)                      //一个FAT表占4个字节
  123.                                                                                                                                             //比如currentClust = 200 那么它所在位置就是800 而一个dataBuffer是512
  124.                                                                                                                                            //字节这样的话800就溢出了所以用800/512=1(整型)这样就读出了它在哪个扇区中
  125.                          ,dataBuffer);                                             
  126.         currentClust = (currentClust << 2) >= 512 ?(currentClust * 4) % 512:currentClust << 2;  
  127.                                                                                                                                            //如上所说下一簇就等于第800/512扇区中的第的第800%512偏移量处
  128.         nextClust = (uint32)(dataBuffer[currentClust]                      //合并4个字节为1个32位数
  129.                         |(dataBuffer[currentClust + 1] << 8)
  130.                         |(dataBuffer[currentClust + 2] << 16)
  131.                         |(dataBuffer[currentClust + 3] << 24));               
  132.         return nextClust;                                                           //返回下一簇的数值
  133. }

  134. /*************************************************************************
  135. *函    数:                delSpace
  136. *作    用:                删除字符串两端的空格
  137. *入口参数:                source(源字符串),string(目地字符串),len(字符个串长度)
  138. *返 回 值:            去掉空格后的字符串长度
  139. *************************************************************************/

  140. uint8 delSpace(buf_t source,buf_t string,uint8 len)
  141. {
  142.         uint8 i;
  143.         uint8 handspace = 0;
  144.         uint8 lastspace = 0;
  145.         for(i = 0;i < len;i ++)                                              //从头部查询
  146.         {
  147.                 if(source[i] == ' ')                                             //发现空格
  148.                         handspace  ++;                                               //字符串头部空格计数器加1
  149.                 else break;                                                      //如发现非空格则退出循环
  150.         }
  151.         for(i = len - 1;i > 0;i --)                                          //从尾部查询
  152.         {
  153.                 if(source[i] == ' ')                                             //发现空格   
  154.                         lastspace ++;                                                                                //字符串尾部空格计数器加1
  155.                 else break;                                                      //如发现非空格则退出循环
  156.         }
  157.         memcpy(string,&source[handspace],len - handspace);             //把有字符串的位置向头部移动   
  158.         if(lastspace != 0)string[len - handspace - lastspace] = 0; //向字符串尾部写0意为字符串到此结束
  159.         return len-handspace-lastspace;                             //返回去掉空格后的字符串长度
  160. }

  161. /*************************************************************************
  162. *函    数:                getFileDate
  163. *作    用:                获取文件日期
  164. *入口参数:                date(从File里读到的文件日期信息),filedate(读出的日期)
  165. *返 回 值:            无
  166. *************************************************************************/
  167. /*
  168. void getFileDate(uint16 date,Date *filedate)
  169. {
  170.         filedate->year = (date >> 9) + 1980;                        //计算年
  171.         filedate->month = (date & 0x1e0) >> 5;                      //计算月
  172.         filedate->day = date & 0x1f;                                //计算日
  173. }

  174. /*************************************************************************
  175. *函    数:                getFileTime
  176. *作    用:                获取文件日期
  177. *入口参数:                time(从File里读到的文件时间信息),filetime(读出的时间)
  178. *返 回 值:            无
  179. *************************************************************************/
  180. /*
  181. void getFileTime(uint16 time,Time *filetime)
  182. {
  183.         filetime->hour = (time &0xf800) >> 11;                      //计算小时
  184.         filetime->minute = (time & 0x7e0) >> 5;                     //计算分钟
  185.         filetime->second = time & 0x1f;                             //计算秒
  186. }

  187. /*************************************************************************
  188. *函    数:                bigToSmall
  189. *作    用:                字符串大小写转换
  190. *入口参数:                string(源字符串),stringd(目地字符串),flag(大写到小是为1 小写到大写为0),len(字符个串长度)
  191. *返 回 值:            无
  192. *************************************************************************/

  193. void bigToSmall(buf_t string,buf_t stringd,flag_t flag,uint8 len)
  194. {
  195.         uint8 i;
  196.         if(flag)                                                                                                        //判断大(小) -> 小(大)
  197.         {
  198.                 for(i = 0;i < len;i ++)                              
  199.                 {
  200.                         if((string[i] >= 'A') && (string[i] <= 'Z'))        //大写到小写的字符范围是'A'-'Z'
  201.                                 stringd[i] = string[i] + 0x20;                  //大写到小写的转换
  202.                         else
  203.                                 stringd[i] = string[i];                         //不在大写字符范围内的不进行转换
  204.                 }
  205.         }else{
  206.                 for(i = 0;i < len;i ++)
  207.                 {
  208.                         if((string[i] >= 'a') && (string[i] <= 'z'))        //小写到大写的字符范围是'a'-'z'
  209.                                 stringd[i] = string[i] - 0x20;                                        //小写到大写的转换
  210.                         else
  211.                                 stringd[i] = string[i];                         //不在小写字符范围内的不进行转换
  212.                 }
  213.         }
  214. }

  215. /*************************************************************************
  216. *函    数:                sectorToClust
  217. *作    用:                扇区和簇之间的换算
  218. *入口参数:                扇区
  219. *返 回 值:            簇
  220. *************************************************************************/

  221. uint32 sectorToClust(uint32 sector)
  222. {
  223.         return sector / dbrInfo.sectorsPerClust;                   //单位换算
  224. }

  225. /*************************************************************************
  226. *函    数:                clustToSector
  227. *作    用:                簇和扇区之间的换算
  228. *入口参数:                簇
  229. *返 回 值:            扇区
  230. *************************************************************************/

  231. uint32 clustToSector(uint32 clust)
  232. {
  233.         return clust * dbrInfo.sectorsPerClust;                    //单位换算
  234. }

  235. /*************************************************************************
  236. *函    数:                dispFileSize
  237. *作    用:                显示文件的大小信息
  238. *入口参数:                size(文件的大小)
  239. *返 回 值:            无
  240. *************************************************************************/
  241. /*
  242. void dispFileSize(uint32 size)
  243. {
  244. #if   DEBUG_TYPE == EN                                                                   //英文终端
  245.         if(size < 1024)                                                                           //不到1K 的
  246.                 printf("size:%dB\r\n",size);                   //直接显示XXB
  247.         if((size > 1024) && (size <0x100000))              //大于1K小于1M的
  248.                 printf("size:%dKB\r\n",size/1024);             //显示XXKB
  249.         if((size > 0x100000) && (size < 0x40000000))           //大于1M小于1G的
  250.                 printf("size:%dMB\r\n",size/0x100000);                   //显示XXMB
  251.         if(size > 0x40000000)                              //大于1G小于1T的
  252.                 printf("size:%dGB\r\n",size/0x40000000);       //显示XXGB
  253. #elif DEBUG_TYPE ==CN
  254.         if(size < 1024)
  255.                 printf("文件大小:%dB\r\n",size);
  256.         if((size > 1024) && (size <0x100000))
  257.                 printf("文件大小:%dKB\r\n",size/1024);
  258.         if((size > 0x100000) && (size < 0x40000000))
  259.                 printf("文件大小:%dMB\r\n",size/0x100000);
  260.         if(size > 0x40000000)
  261.                 printf("文件大小:%dGB\r\n",size/0x40000000);
  262. #endif
  263. }

  264. /*************************************************************************
  265. *函    数:                getFileItem
  266. *作    用:                从当前缓冲区中获取文件信息
  267. *入口参数:                offset(当前缓冲区中的位置 最大值:512)
  268. *返 回 值:            无
  269. *************************************************************************/

  270. void getFileItem(uint16 offset)
  271. {
  272.         fileItem = (File *)&dataBuffer[offset];                //获取文件结构
  273. }

  274. /*************************************************************************
  275. *函    数:                getFileItem
  276. *作    用:                从当前缓冲区中获取文件信息
  277. *入口参数:                offset(当前缓冲区中的位置 最大值:512)
  278. *返 回 值:            无
  279. *************************************************************************/

  280. void getFileLongDirItem(uint16 offset)
  281. {
  282.         longItem = (LongDir *)&dataBuffer[offset];  //获取长目录项结构
  283. }

  284. /*************************************************************************
  285. *函    数:                fileNameProcess
  286. *作    用:                普通文件名转换成短文件名例如:"mp3.txt" >> "MP3     TXT"
  287. *入口参数:                dir(普通文件名),dird(转换好的文件名)
  288. *返 回 值:            无
  289. *************************************************************************/

  290. void fileNameProcess(buf_t dir,buf_t dird)
  291. {
  292.         uint8 i;
  293.         uint8 point = 12;                                 //"."在文件名中的位置
  294.         for(i = 0;i < 8;i ++)                             //主文件名
  295.         {
  296.                 if(dir[i] == 0)goto space;                    
  297.                 if(dir[i] != '.')                             //没有发现"."
  298.                         dird[i] = dir[i];                         //获取短文件名
  299.                 else
  300.                 {                                             //发现"."
  301.                         point = i + 1;                            //记录"."的位置
  302. space:        
  303.                         for(;i < 8;i++)                           
  304.                                 dird[i] = ' ';                        //从"."的位位置填充空格
  305.                 }
  306.         }
  307.         if(dir[8] == '.')point = 9;                       //如第9个字符是"."
  308.         if(point != 12)                                   //如果有"."(为12就是没有".")
  309.         {
  310.                 for(i = 0;i < 3;i ++)                         //获取3个扩展名
  311.                 {
  312.                         if(dir[point + i] != 0)                   //如果没有结束
  313.                                 dird[8 + i] = dir[point + i];         //从"."后面获取扩展名
  314.                         else                                      //如果结束了
  315.                                 for(;i < 3;i ++)                      //剩下的字符填充空格
  316.                                         dird[8 + i] = ' ';
  317.                 }
  318.         }
  319.         else                                              //如果没有"."
  320.                 for(i = 8;i < 11;i ++)                        
  321.                         dird[i] = ' ';                            //全部填充空格
  322.         bigToSmall(dird,dird,SMALL_TO_BIG,11);            //转换成大写
  323. }

  324. /*************************************************************************
  325. *函    数:                openDir
  326. *作    用:                在当前目录下查找文件 如果是文件夹则打开 是文件则返回文件首簇
  327. *入口参数:                dir(文件或文件夹名)
  328. *返 回 值:            文件首簇
  329. *************************************************************************/

  330. uint32 openDir(buf_t dir)
  331. {
  332.         uint16 i;                                 
  333.         uint8 sector;
  334.         uint32 currentClust;
  335.         buf_t tmpString = malloc(11);
  336.         currentClust = currentPath;                                                                           //设置当前簇
  337.         fileNameProcess(dir,tmpString);  
  338.         while(1)
  339.         {        
  340.                 for(sector = 0;sector < dbrInfo.sectorsPerClust;sector ++)                                        //扫描1整簇
  341.                 {
  342.                         readSector(                                                                                   //读一扇区到缓冲区
  343.                                  clustToSector(currentClust - dbrInfo.rootDirClust)                                       //扇区和簇之间的单位转换
  344.                                                                                                                                                                                                                   //当前簇 - 根目录首簇 + 根目录首扇区 = 当前簇首扇区
  345.                                   + sector                                                                                //第"sector"个扇区
  346.                                   + dbrInfo.rootDirSector,                                                                //以根目录首扇区为参考
  347.                                   dataBuffer);                                                                            //读到这里
  348.                         for(i = 0;i < 16;i ++)                                                                        //每个目录项占32个字节512/32 = 16所以要扫描16次
  349.                         {
  350.                                 getFileItem(i *32);                                                                       //从i*32偏移量获取目录项信息
  351.                                 if(stringCmp(tmpString,fileItem->DIR_Name,11))                                            //如果找到文件
  352.                                 {
  353.                                         currentLong = i * 32;                                                                 //获取长目录项用
  354.                                         if(fileItem->DIR_Attr == ATTR_DIRECTORY)                                              //如果是文件夹
  355.                                         {
  356.                                                 currentPath = (uint32)(fileItem->DIR_FstClusHI << 16)|(fileItem->DIR_FstClusLO);  //设置当前目录首簇(相当于进入一个目录)
  357.                                                 free(tmpString);
  358.                                                 return TRUE;                                                                      //返回成功 可以用if(openDir("xxx")) == TRUE
  359.                                                                                                                                                                                                                   //来判读这个文件是文件还是文件夹
  360.                                         }
  361.                                         else
  362.                                         {
  363.                                                         free(tmpString);
  364.                                                         return (uint32)(fileItem -> DIR_FstClusHI << 16)|(fileItem -> DIR_FstClusLO); //如果是文件则返回文件首簇
  365.                                         }
  366.                                 }
  367.                         }
  368.                 }
  369.             currentClust = getNextClust(currentClust);                                                        //根据当前簇获取下一簇
  370.             if((currentClust == ENDCLUST)||(currentClust == BADCLUST)||(currentClust == FIRSTCLUS))           //如果扫描完所有簇还是没有发现要找的文件则返回失败
  371.                 {        
  372.                         free(tmpString);
  373.                         return FALSE;
  374.                 }
  375.         }
  376.         free(tmpString);
  377.         return FALSE;               
  378. }
  379.         

  380. /*************************************************************************
  381. *函    数:                open
  382. *作    用:                返回一个文件所在的簇
  383. *入口参数:                path(文件路径)
  384. *返 回 值:            文件所在的簇
  385. *************************************************************************/

  386. uint32 fileOpen(buf_t path)
  387. {
  388.         uint32 result;
  389.         uint16 i;
  390.         uint8 j = 0;
  391.         buf_t dir;
  392.         dataBuffer = malloc(512);
  393.         dir = malloc(13);                          //开辟一个13个字节的数组
  394.         if(path[0] != '/')                         //判断文件路径
  395.         {
  396.                 i = 0;                                 //非根目录 表示是当前目录
  397.         }else
  398.         {
  399.                 i = 1;                                 //
  400.                 currentPath = dbrInfo.rootDirClust;    //是根目录 切换当前目录至根目录
  401.         }
  402.         while(1)
  403.         {
  404.                 if(path[i] == '/')                     //一个文件或目录名的开始例如:"/usr/src/linux/include/asm-generic/page.c"
  405.                 {
  406.                         dir[j + 1] = '\0';                     
  407.                         openDir(dir);                             //打开目录
  408.                         j = 0;                             //开始一个文件或目录名的获取
  409.                 }else
  410.                 {
  411.                         dir[j] = path[i];                  //获取一个文件或目录名
  412.                     if(path[i] == 0)                   //路径结束
  413.                         {        
  414.                                 result = openDir(dir);                  
  415.                                 free(dir);
  416.                                 free(dataBuffer);
  417.                                 return result;                                   //返回文件或目录的起始簇
  418.                         }
  419.                         j ++;                              //文件或目录字符串中的位置
  420.                 }
  421.                 i++;                                   //路径字符串中的位置
  422.         }
  423. }

  424. /*************************************************************************
  425. *函    数:                read
  426. *作    用:                读文件
  427. *入口参数:                fp(文件首簇),buf(读到的数据),llseek(相对文件首簇的偏移量),len(数据长度 最大不能超过512),flag
  428. *返 回 值:            文件读取结束信息
  429. *************************************************************************/

  430. uint8 fileRead(fp_t fp,buf_t buf,uint32 llseek,uint16 len,flag_t flag)
  431. {
  432.         uint32 currentClust;                                                                 //当前簇
  433.         uint32 var,var_llseek;                                                               
  434.         uint16 i = 0;
  435.         var_llseek = llseek;                                                               
  436.         dataBuffer = malloc(512);                        
  437.         currentClust = fp ;
  438.         var = var_llseek >> 9;
  439.         if(var >= dbrInfo.sectorsPerClust)                                                   //计算偏移量在哪个扇区
  440.         if(flag & FONTFILE_MASK == FONTFILE)                                                 //判断是否是字库文件 因为不加这个读取字库会很慢 加了这个如果有碎片会出意外
  441.                 currentClust = var / dbrInfo.sectorsPerClust + currentClust ;                    //从偏移量中计算出当前簇;
  442.         else
  443.         {
  444.             i = (var / dbrInfo.sectorsPerClust) ;                                            //计算从文件头部到偏移量有多少簇
  445.                 while(i-- )                                                                      //挨个簇查询
  446.                 {
  447.                         currentClust = getNextClust(currentClust);                                   //获取下一簇
  448.                     if((currentClust == ENDCLUST)\
  449.                     || (currentClust == BADCLUST)\
  450.                         || (currentClust == FIRSTCLUS))                                              //有坏簇或到终点返回
  451.                         {
  452.                                 free(dataBuffer);
  453.                                 return FALSE;
  454.                         }
  455.                 }
  456.         }
  457.         readSector(clustToSector(currentClust - dbrInfo.rootDirClust)\
  458.                             + (var % dbrInfo.sectorsPerClust) + dbrInfo.rootDirSector,dataBuffer);  //先从偏移位置读取一扇区数据
  459.         for(i = 0;i < len;i ++)                                                             //把有用数据放进缓冲区
  460.         {
  461.                 if((i + var_llseek % 512) >= 512)                                               //如果读取过程中超出当前扇区
  462.                 {
  463.                         var_llseek = 0;                                                             //下一个扇区从头读取
  464.                         if(((var + 1) % dbrInfo.sectorsPerClust) == 0)                              //如果读取过程中超出当前簇
  465.                         {
  466.                                 currentClust = getNextClust(currentClust);                              //获取下一簇
  467.                             if((currentClust == ENDCLUST)\
  468.                                 || (currentClust == BADCLUST)\
  469.                                 || (currentClust == FIRSTCLUS))                                         //有坏簇或到终点返回
  470.                                 {
  471.                                         free(dataBuffer);
  472.                                         return FALSE;
  473.                                 }
  474.                                 readSector(clustToSector(currentClust - dbrInfo.rootDirClust)\
  475.                                          +        ((var + 1) % dbrInfo.sectorsPerClust)\
  476.                                           + dbrInfo.rootDirSector ,dataBuffer);                            //读取下个簇的第一个扇区
  477.                         }else
  478.                                 readSector(clustToSector(currentClust - dbrInfo.rootDirClust)\
  479.                                  + (var % dbrInfo.sectorsPerClust)\
  480.                                   + dbrInfo.rootDirSector + 1,dataBuffer);                             //读取下个扇区
  481.                 }
  482.                 buf[i] = dataBuffer[i + var_llseek % 512];                                     //收集有用数据
  483.         }
  484.         free(dataBuffer);
  485.         return TRUE;
  486. }

  487. /*************************************************************************
  488. *函    数:                getFileLongName
  489. *作    用:                从当前文件中获取文件长目录项信息
  490. *入口参数:                string(获取到的长文件名)
  491. *返 回 值:            无
  492. *************************************************************************/

  493. void getFileLongName(buf_t string)
  494. {
  495.         uint8 val,val1,i,item;
  496.         item = 0;
  497.         uint32 offset;
  498.         offset = currentLong;
  499.         if(offset > 31)getFileLongDirItem(offset-32);                                      //获取当前文件的长目录结构
  500.         if((longItem->LDIR_Attr == ATTR_LONG_NAME) && (offset > 31))                       //如里是长目录项并
  501.         {
  502.                 val = checkNameSum(fileItem->DIR_Name);                                        //获取文件效验和
  503.                 if(val == longItem->LDIR_Chksum)                                               //对比文件效验和
  504.                 {
  505.                         do{
  506.                                         getFileLongDirItem(offset-((item + 1) << 5));                      //获取当前文件的长目录结构的子项
  507.                                         for(i = 0;i < 13;i ++)                                             //第个子项是13个字符
  508.                                         {
  509.                                                 if(i < 5)                                                      //第1-5个字符
  510.                                                 {
  511.                                                         if(longItem->LDIR_Name1[i] == 0xffff)                      //是否结束
  512.                                                         {
  513.                                                                 string[i + (item * 13) + 1] = 0;                       //设置结束
  514.                                                                 return;                                                //退出
  515.                                                         }
  516.                                                         if(longItem->LDIR_Name1[i] < 0x100)                        //是否Unicode
  517.                                                                 string[i + (item * 13)] = longItem->LDIR_Name1[i];     //从长目录项中获取字符
  518.                                                         else
  519.                                                         {
  520.                                                                 UnitoAsc(longItem -> LDIR_Name1[i]);                   //把Unicode转换成ASCII
  521.                                                                 string[i + (item * 13)] = longItem -> LDIR_Name1[i];     
  522.                                                         }                                                                                                   //是Unicode
  523.                                                 }
  524.                                                 if((i > 4)&&(i < 11))                                          //第6-11个字符
  525.                                                 {
  526.                                                         if(longItem->LDIR_Name2[i - 5] == 0xffff)                  //是否结束
  527.                                                         {
  528.                                                                 string[i + (item * 13) + 1] = 0;                       //设置结束
  529.                                                                 return;                                                //退出
  530.                                                         }
  531.                                                         if(longItem->LDIR_Name2[i - 5] < 0x100)                    //是否Unicode
  532.                                                                 string[i + (item * 13)] = longItem->LDIR_Name2[i - 5]; //从长目录项中获取字符
  533.                                                         else
  534.                                                         {
  535.                                                                 UnitoAsc(longItem -> LDIR_Name2[i]);
  536.                                                                 string[i + (item * 13)] = longItem -> LDIR_Name2[i];   //把Unicode转换成ASCII
  537.                                                         }                                                                                                   
  538.                                                 }
  539.                                                 if (i > 10)                                                    //第12-13个字符
  540.                                                 {
  541.                                                         if(longItem->LDIR_Name3[i - 11] == 0xffff)                 //是否结束
  542.                                                         {
  543.                                                                 string[i + (item * 13) + 1] = 0;                       //设置结束
  544.                                                                 return;                                                //退出
  545.                                                         }
  546.                                                         if(longItem->LDIR_Name3[i - 11] < 0x100)                   //是否Unicode
  547.                                                                 string[i + (item * 13)] = longItem->LDIR_Name3[i - 11];//从长目录项中获取字符
  548.                                                         else
  549.                                                         {
  550.                                                                 UnitoAsc(longItem -> LDIR_Name3[i]);
  551.                                                                 string[i + (item * 13)] = longItem -> LDIR_Name3[i];   //把Unicode转换成ASCII
  552.                                                         }                                                                                                   
  553.                                                 }
  554.                                         }
  555.                                         item ++;                                                           //子项计数
  556.                                 }
  557.                                 while(!(longItem->LDIR_Ord & 0x40));                                   //是否最后一个子项
  558.                 }
  559.         }
  560.         else
  561.         {
  562.                 if(fileItem->DIR_LowCase & FILE_NAME_SMALL)
  563.                         bigToSmall(fileItem->DIR_Name,string,BIG_TO_SMALL,8);                      //如果文件名是小写就把短文件名转换成小写
  564.                 else
  565.                         bigToSmall(fileItem->DIR_Name,string,SMALL_TO_BIG,8);                                           //否则转换成大写
  566.                 if(fileItem->DIR_LowCase & FILE_EXT_SMALL)
  567.                         bigToSmall(&fileItem->DIR_Name[8],&string[8],BIG_TO_SMALL,3);              //如果扩展名是小写就把短文件名中的扩展名小写
  568.                 else
  569.                         bigToSmall(&fileItem->DIR_Name[8],&string[8],SMALL_TO_BIG,3);              //否则转换成大写
  570.                 val = delSpace(string,string,8);                                               //删除空格
  571.                 string[val] = '.';                                                             //设置'.'
  572.                 if(strncmp(&fileItem->DIR_Name[8],"   ",3) != 0)                               //扩展名是否为空
  573.                 {
  574.                         val1 = delSpace(&string[8],&string[val + 1],3);                            //如不为空删除空格并连接文件名和扩展名
  575.                         string[val1 + val + 1] = 0;                                                //设置结束
  576.                 }else
  577.                         string[val] = 0;                                                           //为空就不设置'.'
  578.         }
  579. }        
复制代码


主程序:
  1. #include "config.h"
  2. #include "drivers/uart.h"
  3. #include "drivers/mmc.h"
  4. #include "fs/fat32.h"
  5. #include "drivers/lcd.h"
  6. #include "logo.h"
  7. #include "gui/font.h"
  8. #include "gui/gui_window.h"
  9. #include "gui/gui_explorer.h"
  10. int main()
  11. {
  12.         uint32 fp;
  13.         uint32 i;
  14.         buf_t dataBuffer;
  15.         dataBuffer = malloc(512);
  16.         PORTA = 0xff;
  17.         PORTB = 0xff;
  18.         DDRA = 0xff;
  19.         DDRB = 0xff;
  20.         Uart_Initialize(9600);
  21.         LCD_Initialize();
  22.          GUI_DrawBitMap(image1,0,0,240,127,PROGRAM|SUN);
  23. //        while(1);
  24.         
  25. back:
  26.         if(MMC_Initialize() == FALSE){printf("MMC卡错误\r\n");_delay_ms(1000);goto back;}
  27.         if(FAT_Initialize(0) == FALSE)
  28.                 printf("MMC卡错误\r\n");
  29.         else
  30.         {
  31. //                GUI_DrawBitMap(lkj,0,0,16,16,RAMCODE|SUN);
  32.                 Font_Initialize();
  33.                 fp = fileOpen("/admin.txt");
  34. //                getFileLongName(dataBuffer);
  35. //                printf("fp = %d\r\n",fp);
  36.                 fileRead(fp,dataBuffer,0,512,0);
  37. //                GUI_Explorer("/backup~1.dbk");

  38. //                printf("dataBuffer = %s\r\n",dataBuffer);
  39.                 LCD_PutString12(dataBuffer,0,0,RAMCODE|SUN);
  40. //                LCD_PutString16(dataBuffer,0,0,RAMCODE|SUN);
  41.         }
  42. //        LCD_ClearRAM();
  43.         free(dataBuffer);
  44.         while(1);
  45. }
复制代码

所有资料51hei提供下载:
AVR32 SD FAT32.7z (1.02 MB, 下载次数: 57)

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:1 发表于 2018-10-10 19:38 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:556433 发表于 2019-12-9 23:18 | 显示全部楼层
谢谢分享~下载下来学习学习!
回复

使用道具 举报

ID:82098 发表于 2020-3-14 22:43 | 显示全部楼层
本帖最后由 zlkj 于 2020-3-21 13:58 编辑

感谢分享!可以发个STM32F4的仿真吗?260096@163.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表