搜索
bottom↓
回复: 9

关于SD 文件系统znfat问题

[复制链接]

出0入0汤圆

发表于 2013-8-16 16:43:50 | 显示全部楼层 |阅读模式
请教下,我的问题的SD卡可以初始化,然而到了znfat初始化的时候初始化不了为什么

#include "znfat.h"
#include "sd.h"        //存储设备的扇区读写驱动,这里是SD卡
#include "string.h"
sbit P10=P1^0;
//全局变量定义
struct direntry idata temp_rec;
INT8 temp_dir_name[13];
UINT32 temp_dir_cluster;
UINT32 temp_last_cluster;

UINT8 FAT32_Buffer[512]; //扇区数据读写缓冲区,由外部提供

extern struct FAT32_Init_Arg *pArg; //初始化参数结构体指针,用以指向某一存储设备的初始化参数结构体,由外部提供

unsigned char (*pRS)(unsigned long,unsigned char *); //指向实际存储设备的读扇区函数的函数指针,用以实现对设备的支持
unsigned char (*pWS)(unsigned long,unsigned char *); //指向实际存储设备的写扇区函数的函数指针,用以实现对设备的支持

extern unsigned char Dev_No;

/******************************************************************
- 功能描述:znFAT的存储设备底层驱动接口,读取存储设备的addr扇区的
             512个字节的数据放入buf数据缓冲区中
- 隶属模块:znFAT文件系统模块
- 函数属性:内部(用于与存储设备的底层驱动对接)
- 参数说明:addr:扇区地址
             buf:指向数据缓冲区
- 返回说明:0表示读取扇区成功,否则失败
- 注:这里加入了天狼星精华板上的三种存储设备,即SD卡(有效)、U盘、
       CF卡通过在程序中动态的切换不同的设备驱动,从而实现多设备(即同
           时对多种存储设备进行操作,比如从SD卡拷贝文件到U盘等等),不同
           驱动的切换,只需要在程序中改变Dev_No这个全局变量的值即可
******************************************************************/

UINT8 FAT32_ReadSector(UINT32 addr,UINT8 *buf)
{
switch(Dev_No)
{
  case SDCARD:
         pRS=SD_Read_Sector;
         break;
  case UDISK:
         //pRS=CH375_Read_Sector;
         break;
  case CFCARD:
         //pRS=CF_Read_Sector;
         //无
         break;
  case OTHER:
         //无
         break;
}
return (*pRS)(addr,buf);  //替换成实际存储器的扇区读函数,这里是SD卡扇区读函数
}

/******************************************************************
- 功能描述:znFAT的存储设备底层驱动接口,将buf数据缓冲区中的512个
             字节的数据写入到存储设备的addr扇区中
- 隶属模块:znFAT文件系统模块
- 函数属性:内部(用于与存储设备的底层驱动对接)
- 参数说明:addr:扇区地址
             buf:指向数据缓冲区
- 返回说明:0表示读取扇区成功,否则失败
- 注:略
******************************************************************/

UINT8 FAT32_WriteSector(UINT32 addr,UINT8 *buf)
{
switch(Dev_No)
{
  case SDCARD:
         pWS=SD_Write_Sector;
         break;
  case UDISK:
         //pWS=CH375_Write_Sector;
         break;
  case CFCARD:
         //pWS=CF_Write_Sector;
         //无
         break;
  case OTHER:
         //无
         break;
}
return (*pWS)(addr,buf); //替换成实际存储器的扇区写函数,这里是SD卡扇区写函数
}

/******************************************************************
- 功能描述:小端转大端,即LittleEndian车BigEndian
- 隶属模块:znFAT文件系统模块
- 函数属性:内部
- 参数说明:dat:指向要转为大端的字节序列
             len:要转为大端的字节序列长度
- 返回说明:转为大端模式后,字节序列所表达的数据
- 注:比如:小端模块的       0x33 0x22 0x11 0x00  (低字节在前)
             转为大端模式后为 0x00 0x11 0x22 0x33  (高字节在前)
             所表达的数值为   0x00112233
             (CISC的CPU通常是小端的,所以FAT32也设计为小端,而单片机
              这种RISC的CPU,通常来说都是大端的,所以需要这个函数将字
              节的存放次序进行调整,才能得到正确的数值)
******************************************************************/

UINT32 LE2BE(UINT8 *dat,UINT8 len)
{
UINT32 temp=0;
UINT32 fact=1;
UINT8  i=0;
for(i=0;i<len;i++)
{
  temp+=dat[i]*fact;
  fact*=256;
}
return temp;
}

/******************************************************************
- 功能描述:将小字字符转为大写
- 隶属模块:znFAT文件系统模块
- 函数属性:内部
- 参数说明:c:要转换为大写的字符            
- 返回说明:要转换的字节的相应的大写字符
- 注:只对小写字符有效,如果不是a~z的小写字符,将直接返回
******************************************************************/

INT8 L2U(INT8 c)
{
if(c>='a' && c<='z') return c+'A'-'a';
else return c;
}

/******************************************************************
- 功能描述:读取0扇区,检测有没有MBR(主引导记录)
- 隶属模块:znFAT文件系统模块
- 函数属性:内部
- 参数说明:无     
- 返回说明:1表示检测到MBR,0表示没有检测到MBR
- 注:有些存储设备格式化为FAT32以后,没有MBR,则0扇区就是DBR
       如果有MBR,就需要对其进行解析,以得到DBR的扇区位置,同时MBR中
       还含分区、分区容量等信息
******************************************************************/

UINT8 FAT32_is_MBR()
{
UINT8 result;
FAT32_ReadSector(0,FAT32_Buffer);
if(FAT32_Buffer[0]!=0xeb)
{
  result=1;
}
else
{
  result=0;
}
return result;
}

/***********************************************************************
- 功能描述:得到DBR所在的扇区号(如果没有MBR,则DBR就在0扇区)
- 隶属模块:znFAT文件系统模块
- 函数属性:内部
- 参数说明:无     
- 返回说明:DBR的扇区地址
- 注:DBR中包含了很多有用的参数信息,因此正确定位DBR扇区的位置,是极为
       重要的,后面将有专门的函数对DBR进行解析,正确解析DBR是实现FAT32的
       基础
***********************************************************************/

UINT16 FAT32_Find_DBR()
{
UINT16 sec_dbr;
FAT32_ReadSector(0,FAT32_Buffer);
if(FAT32_Buffer[0]!=0xeb)
{
  sec_dbr=LE2BE(((((struct PartSector *)(FAT32_Buffer))->Part[0]).StartLBA),4);
}

else
{
  sec_dbr=0;
}
return sec_dbr;
}

/***********************************************************************
- 功能描述:获取分区的总容量
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:无     
- 返回说明:分区容量值,单位为字节
- 注:这里得到的总容量是FAT32分区的容量,一定小于实际的物理容量
***********************************************************************/

UINT32 FAT32_Get_Total_Size()
{
UINT32 temp;
FAT32_ReadSector(pArg->BPB_Sector_No,FAT32_Buffer);
FAT32_ReadSector(pArg->BPB_Sector_No,FAT32_Buffer);
temp=((LE2BE((((struct FAT32_BPB *)(FAT32_Buffer))->BPB_TotSec32),4)))*pArg->BytesPerSector;
return temp;
}

/***********************************************************************
- 功能描述:读取FSInfo获取最近的一个可用空闲簇
- 隶属模块:znFAT文件系统模块
- 函数属性:内部
- 参数说明:无     
- 返回说明:最近的一个可用空闲簇
- 注:FAT32中的FSInfo扇区(绝对1扇区)中记录了最近的一个可用空闲簇
***********************************************************************/

UINT32 Search_Last_Usable_Cluster()
{
FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
return LE2BE(((struct FSInfo *)FAT32_Buffer)->Last_Cluster,4);
}

/***********************************************************************
- 功能描述:FAT32文件系统初始化
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:FAT32_Init_Arg类型的结构体指针,用于装载一些重要的参数信息,
             以备后面使用     
- 返回说明:无
- 注:在使用znFAT前,这个函数是必须先被调用的,将很多参数信息装入到
       arg指向的结构体中,比如扇区大小、根目录的位置、FAT表大小等等。
       这些参数绝大部分是来自于DBR的BPB中,因此此函数主要在作对DBR的参数解析
***********************************************************************/

void FAT32_Init()
{

struct FAT32_BPB *bpb;

bpb=(struct FAT32_BPB *)(FAT32_Buffer);               //将数据缓冲区指针转为struct FAT32_BPB 型指针

pArg->DEV_No=Dev_No; //装入设备号

pArg->BPB_Sector_No   =FAT32_is_MBR();               //FAT32_FindBPB()可以返回BPB所在的扇区号
pArg->BPB_Sector_No   =FAT32_Find_DBR();               //FAT32_FindBPB()可以返回BPB所在的扇区号
pArg->Total_Size      =FAT32_Get_Total_Size();         //FAT32_Get_Total_Size()可以返回磁盘的总容量,单位是兆
pArg->Total_Size      =FAT32_Get_Total_Size();         //FAT32_Get_Total_Size()可以返回磁盘的总容量,单位是兆

pArg->FATsectors      =LE2BE((bpb->BPB_FATSz32)    ,4);//装入FAT表占用的扇区数到FATsectors中
pArg->FirstDirClust   =LE2BE((bpb->BPB_RootClus)   ,4);//装入根目录簇号到FirstDirClust中
pArg->BytesPerSector  =LE2BE((bpb->BPB_BytesPerSec),2);//装入每扇区字节数到BytesPerSector中
pArg->SectorsPerClust =LE2BE((bpb->BPB_SecPerClus) ,1);//装入每簇扇区数到SectorsPerClust 中
pArg->FirstFATSector  =LE2BE((bpb->BPB_RsvdSecCnt) ,2)+pArg->BPB_Sector_No;//装入第一个FAT表扇区号到FirstFATSector 中
pArg->FirstDirSector  =(pArg->FirstFATSector)+(bpb->BPB_NumFATs[0])*(pArg->FATsectors); //装入第一个目录扇区到FirstDirSector中

temp_last_cluster=Search_Last_Usable_Cluster();
}

/***********************************************************************
- 功能描述:获取剩余容量
- 隶属模块:znFAT文件系统模块
- 函数属性:外部,使用户使用
- 参数说明:无   
- 返回说明:剩余容量,单位字节
- 注:从FSInfo中读取空闲簇数,而从计算得到剩余的容量,单位字节
***********************************************************************/

UINT32 FAT32_Get_Remain_Cap()
{
FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);
if(((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]==0xff
&& ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]==0xff
&& ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]==0xff
&& ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]==0xff)
return pArg->Total_Size;
else
return LE2BE(((struct FSInfo *)FAT32_Buffer)->Free_Cluster,4)*pArg->SectorsPerClust*pArg->BytesPerSector;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2013-8-16 16:45:22 | 显示全部楼层
自己先顶下……请教帮忙,

出0入0汤圆

发表于 2013-8-16 17:24:47 | 显示全部楼层
1.我不知道爲甚麼。
2.提醒,發代碼,宜精簡,且用[co de][/co de]包圍(去掉空格)。
3.本回覆旨在挽回你的尊嚴,簡稱“挽尊”。
4.建議自己做,不要想着移植。
5.于震南不是甚麼好人,人品有點問題。

出0入0汤圆

发表于 2013-8-16 17:47:41 | 显示全部楼层
本帖最后由 john800422 于 2013-8-16 17:49 编辑
qlb1234 发表于 2013-8-16 17:24
1.我不知道爲甚麼。
2.提醒,發代碼,宜精簡,且用[co de][/co de]包圍(去掉空格)。
3.本回覆旨在挽回你 ...


之前都不知道
學習了[co de][/co de]

試試看效果

[co de]
UINT32 FAT32_Get_Remain_Cap()
{
    FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);

    if(((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]==0xff
    && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]==0xff
    && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]==0xff
    && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]==0xff)
        return pArg->Total_Size;
    else
        return LE2BE(((struct FSInfo *)FAT32_Buffer)->Free_Cluster,4)*pArg->SectorsPerClust*pArg->BytesPerSector;
}
[/co de]

  1. UINT32 FAT32_Get_Remain_Cap()
  2. {
  3.     FAT32_ReadSector(1+pArg->BPB_Sector_No,FAT32_Buffer);

  4.     if(((struct FSInfo *)FAT32_Buffer)->Free_Cluster[0]==0xff
  5.     && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[1]==0xff
  6.     && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[2]==0xff
  7.     && ((struct FSInfo *)FAT32_Buffer)->Free_Cluster[3]==0xff)
  8.         return pArg->Total_Size;
  9.     else
  10.         return LE2BE(((struct FSInfo *)FAT32_Buffer)->Free_Cluster,4)*pArg->SectorsPerClust*pArg->BytesPerSector;
  11. }
复制代码

出0入0汤圆

 楼主| 发表于 2013-8-16 23:11:00 | 显示全部楼层
qlb1234 发表于 2013-8-16 17:24
1.我不知道爲甚麼。
2.提醒,發代碼,宜精簡,且用[co de][/co de]包圍(去掉空格)。
3.本回覆旨在挽回你 ...

谢谢,我会注意的,

出0入0汤圆

 楼主| 发表于 2013-8-16 23:16:01 | 显示全部楼层
ballack_linux 发表于 2013-8-16 18:32
你初始化不了 可以通过串口查看错误码,文件中定义了每个错误码代表什么意思的,而且首先你要确定你的SD卡 ...

串口?我有过一步一步的点亮LED灯过,是初始化里的find_DBR里有问题,感觉是里面的写数组有问题,现在是怀疑我的SD卡有点坑,用的不是正宗的SD卡,用的是TF+SD卡槽和成的SD卡,考虑换个SD卡试试

出0入0汤圆

 楼主| 发表于 2013-8-16 23:16:54 | 显示全部楼层
john800422 发表于 2013-8-16 17:47
之前都不知道
學習了[co de][/co de]

谢谢,我会注意的啊,新手,你们莫怪,

出0入0汤圆

 楼主| 发表于 2013-8-19 19:59:15 | 显示全部楼层
ballack_linux 发表于 2013-8-19 14:14
你移植的代码里面没有串口调试那一块吗??  如果你没调出来,你可以看看我发的MP3的帖子 ...

有的,我用了的,就死在FAt的初始化上,我初始化后面的显示不出来,

出0入0汤圆

 楼主| 发表于 2013-8-20 22:17:44 | 显示全部楼层
ballack_linux 发表于 2013-8-20 09:11
UINT8 znFAT_Init(void)这个函数由三个值返回,0:成功,1:不成功,2:非FAT32文件系统。你可以在这个函数 ...

好的,一定的

出0入0汤圆

 楼主| 发表于 2013-8-21 20:07:16 | 显示全部楼层
晓毕8 发表于 2013-8-20 22:17
好的,一定的

修改好了,是我的卡坏的,郁闷了啊,好在去去换了,不然找死都找不到啊……

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 16:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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