[讨论] FATFS文件系统问题求助

cuizhihao   2010-7-16 18:45 楼主

    菜鸟求助喽……高手赐教哦……

这几天学习FATFS文件系统,上网查资料说是这可以移植到51AVRARM等各种微控制器中,其FATFS特点如下:

1、分离缓冲的FAT结构和每一个文件,适合快速访问多个文件。

2、支持多个驱动器和分区。

3、支持FAT12 FAT16FAT32

4、支持8.3格式的文件名(LFN不支持)

5、支持两个分区规则: Fdisk和超级软盘。

6、优化8/16-bit微控制器。

FatFs Module一开始就是为了能在不同的单片机上使用而设计的,所以具有良好的层次结构,如图1所示。最顶层是应用层,使用者无需理会FatFs Module的内部结构和复杂的FAT协议,只需要调用FatFs Module提供给用户的一系列应用接口函数,f_open,f_read,f_writef_close等,就可以像在PC上读/写文件那样简单。

 

clip_image002.jpg

中间层FatFs Module实现了FAT文件读/写协议。FatFs Module的完全版提供的是ffcffH,除非有必要,使用者一般不用修改,使用时将需要版本的头文件直接包含进去即可。需要使用者编写移植代码的是FatFs Module提供的底层接口,它包括存储媒介读/写接口DiskIO和供给文件创建修改时间的实时时钟,包括{

disk_initialize -初始化的磁盘驱动器

              disk_status -获取磁盘状态

              disk_read -读部门(星期日)

              disk_write -收件部门(星期日)

              disk_ioctl -控制装置依赖功能

              get_fattime -获取当前时间                     }等这些函数。

              我做过这些工作后,调试,没成功,错误发现时在发送过复位命令后在激活的过程中,激活命令发出后,便一直在等待响应,然后超时就返回了。 clip_image003.jpg

下面是我写的底层接口函数,高手看看哪里有错误,指教一下,万分感激!

#include<LPC213x.h>

#include"config.h"

#include "diskio.h"

#include"integer.h"

 

/* Definitions for MMC/SDC command */

#define CMD0       (0x40+0) /* GO_IDLE_STATE */

#define CMD1       (0x40+1) /* SEND_OP_COND (MMC) */

#define CMD9       (0x40+9) /* SEND_CSD */

#define CMD10      (0x40+10)      /* SEND_CID */

#define CMD12      (0x40+12)      /* STOP_TRANSMISSION */

#define ACMD13    (0xC0+13)      /* SD_STATUS (SDC) */

#define CMD16      (0x40+16)      /* SET_BLOCKLEN */

#define CMD17      (0x40+17)      /* READ_SINGLE_BLOCK */

#define CMD18      (0x40+18)      /* READ_MULTIPLE_BLOCK */

#define CMD24      (0x40+24)      /* WRITE_BLOCK */

#define CMD25      (0x40+25)      /* WRITE_MULTIPLE_BLOCK */

#define CMD55      (0x40+55)      /* APP_CMD */

#define CMD58      (0x40+58)      /* READ_OCR */

#define ACMD41    (0xC0+41)

 

BYTE respbuf[5];

 

static volatile

DSTATUS Stat = STA_NOINIT;   /* Disk status */

 

/*******************************************************************************************************************

** 函数名称: void SD_Power()                               Name:       void SD_Power()

** 功能描述: 对卡先下电,再上电                                 Function: turn off the card's power, and turn on

** 输   :                                                            Input:        NULL

**   :                                                            Output:      NULL

********************************************************************************************************************/

void SD_Power(void)

{

       UINT i;

 

       SD_POWER_GPIO();

       SD_POWER_OUT();

       SD_POWER_OFF();                                                      /* 关闭 SD 卡电源  turn off power of sd card */

      

       SPI_SCK_GPIO();

       SPI_SCK_OUT();

       SPI_SCK_CLR();                                                    /* SCK  引脚置低   set SCK to zero */

      

       SPI_MISO_GPIO();

       SPI_MISO_OUT();

       SPI_MISO_CLR();                                                  /* MISO 引脚置低   set MISO to zero */

      

       SPI_MOSI_GPIO();            

       SPI_MOSI_OUT();

       SPI_MOSI_CLR();                                                  /* MOSI 引脚置低   set MOSI to zero */

      

       SPI_CS_GPIO();                                                   

     SPI_CS_OUT();                                                     

       SPI_CS_CLR();                                                      /* CS 引脚置低       set CS to zero */

             

       for(i = 0; i < 0x9000; i++);                         /* 关闭电源延时    delay after turn off power of sd card */

       SD_POWER_ON();                                                        /* 打开 SD 卡电源  turn on power of sd card */

}

/*******************************************************************************************************************

** 函数名称: void SD_HardWareInit()                      Name:       void SD_HardWareInit()

** 功能描述: 初始化访问SD卡的硬件条件                  Function: initialize the hardware condiction that access sd card

** 输   :                                                            Input:        NULL

**   :                                                            Output:      NULL

********************************************************************************************************************/

void SD_HardWareInit(void)

{

       SD_Power();                                                          /* 对卡先下电,再上电  turn off power of card, and turn on it */

      

       SPI_INIT();                                                           /* 初始化SPI接口      initialize SPI interface */   

      

       SD_INSERT_GPIO();

       SD_INSERT_IN();                                                  /* 检测卡完全插入口为输入口   the port checking card is input */

      

       SD_WP_GPIO();                                                   

       SD_WP_IN();                                                         /* 写保护检测口为输入口          the port written protect is input */      

                

     SPI_CS_SET();                                                      /* CS置高                                  set CS to high voltage */

 

      S0SPCCR = 128;                                                    /* 设置SPI频率小于等于400kHZ  set frequency of SPI below 400kHZ */

  

      S0SPCR = (0x01 << 4) + (0x01 << 5);              /* 设置SPI接口模式,MSTR = 1,CPOL = 1,CPHA = 0,LSBF=0 */

}                                                                                  /* configure SPI interface */

 

BYTE SPI_SendByte(BYTE dat)

{

       BYTE temp;

 

       S0SPDR = dat;                                                /* 发送数据放入SPI数据寄存器 */

  

       while(0 == (S0SPSR & 0x80));                         /* 等待SPIF置位,即等待数据发送完毕 */

                                                                                    /* wait for SPIF being set, that is, wait for finishing of data being send */

      temp = S0SPDR;

       return      temp;

}

 

void SD_SPIDelay(BYTE value)

{

    BYTE i;

 

    for (i = 0; i < value; i++)

        SPI_SendByte(0xFF);                                            /* 发送0xFF clock out 0xFF */

}

 

 

              /*********************************************************

             

                                       下面为一些数据传输函数

             

              **********************************************************/

BOOL Read_BlockData(BYTE *buffer,UINT count)

{

       BYTE      tmp;

       UINT      i;

       SPI_CS_CLR();

       i      = 69120;

       do

       {

              tmp = SPI_SendByte(0xff);

       }while((tmp == 0xff)&&(i--));

       if(i==0)          return  FALSE;

       if(tmp != 0xfe)       return      FALSE;

       for(i=0;i<count;i++)

       {

              buffer = SPI_SendByte(0xff);

       }

       SPI_SendByte(0xff);

       SPI_SendByte(0xff);

       SPI_CS_SET();

       SPI_SendByte(0xff);

       return      TRUE;

}

 

 

#if _READONLY == 0

BOOL Write_BlockData(BYTE *buffer,BYTE token)

{

       BYTE      tmp;

       UINT      count;

       SPI_CS_CLR();

       SPI_SendByte(0xff);

       SPI_SendByte(token);

       if(token != 0xfd)

       {

              count      = 512;

              while(count--) SPI_SendByte(*buffer++);

              SPI_SendByte(0xff);

              SPI_SendByte(0xff);

              tmp         = SPI_SendByte(0xff);

              if((tmp&0x1f) != 0x05) return      FALSE;

       }

       return      TRUE;

}

#endif /* _READONLY */

 

 

BOOL SD_SendCmd( BYTE cmd, UINT arg, BYTE resptype, BYTE *resp)

{

        BYTE    tmp,i;

        CHAR   j;

        if (cmd & 0x80) {       /* ACMD<n> is the command sequense of CMD55-CMD<n> */

        cmd &= 0x7F;

        tmp = SD_SendCmd(CMD55, 0);

        if (tmp != TRUE) return FALSE;

    }

       SPI_CS_CLR();

       SPI_SendByte(0xff);                       //发命令前延时8SPI时钟

 

       SPI_SendByte(cmd);

       SPI_SendByte(arg >> 24);

       SPI_SendByte(arg >> 16);

       SPI_SendByte(arg >> 8);

       SPI_SendByte(arg);

       SPI_SendByte(0x95);

       i = 100;

       do

       {

              tmp = SPI_SendByte(0xff);

       }while(((tmp&0x80) != 0) && (i--));

       if(i==0)   return      FALSE;

       for(j=resptype-1;j >= 0;j--)

       {

              resp[j] =  SPI_SendByte(0xff);

       }

       SPI_SendByte(0xff);

       SPI_CS_SET();

       SPI_SendByte(0xff);

       return      TRUE;

}

/*--------------------------------------------------------------------------

 

  Public Functions

 

  ---------------------------------------------------------------------------*/

 

 

/*-----------------------------------------------------------------------*/

/* Initialize Disk Drive                                                 */

/*-----------------------------------------------------------------------*/

 

DSTATUS disk_initialize (

        BYTE drv              /* Physical drive nmuber (0) */

        )

{

       BYTE      tmp,ocrbuf[4];

       UINT      j;

       if (drv) return STA_NOINIT;                         /* Supports only single drive */

    if (Stat & STA_NODISK) return Stat;              /* No card in the socket */

       SD_HardWareInit();

       if(SD_INSERT_STATUS() != 0)          return 0;

       SPI_CS_CLR();

       SD_SPIDelay(25);

       SPI_CS_SET();

       SD_SPIDelay(2);

       tmp = SD_SendCmd( CMD0, 0, 1, respbuf);

       if(tmp != 1)    return  0;

       j=0;

       SD_SendCmd( ACMD41, 0, 1, respbuf);

       do{

              tmp = SD_SendCmd( CMD1, 0, 1, respbuf);

              if(tmp != 1)    return      0;

              j++;

          }while(((respbuf[0]&0x01) == 0x01) &&(j < 1000));

       if(j >= 1000)   return      0;

       tmp =  SD_SendCmd( CMD58, 0, 5, respbuf);

       if(tmp != 1)    return      0;

       if(respbuf[0] != 0)         return      0;

       for(j=0;j<4;j++)

       {

              ocrbuf[j] = respbuf[j+1];

       }

       if((ocrbuf[1]&0xc0) != 0xc0)      return      0;

       S0SPCCR = 8;

       tmp = SD_SendCmd(CMD16,512,1,respbuf);

       if(tmp != 1)    return 0;

       return      RES_OK;

}

/*-----------------------------------------------------------------------*/

/* Get Disk Status                                                       */

/*-----------------------------------------------------------------------*/

 

DSTATUS disk_status (

        BYTE drv              /* Physical drive nmuber (0) */

        )

{

    if (drv) return STA_NOINIT;              /* Supports only single drive */

    return Stat;

}

/*-----------------------------------------------------------------------*/

/* Read Sector(s)                                                        */

/*-----------------------------------------------------------------------*/

 

DRESULT disk_read (

        BYTE drv,                    /* Physical drive nmuber (0) */

        BYTE *buff,                 /* Pointer to the data buffer to store read data */

        DWORD sector,                    /* Start sector number (LBA) */

        BYTE count                  /* Sector count (1..255) 扇区数*/

        )

{

    if (drv || !count) return RES_PARERR;

    if (Stat & STA_NOINIT) return RES_NOTRDY;

 

       sector *= 512;

       if(count == 1)

       {

              if(SD_SendCmd( CMD17, sector, 1, respbuf) && Read_BlockData(buff, 512))

              count = 0;

       }

       else

       {

              if(SD_SendCmd( CMD18, sector, 1, respbuf))

              {

                     do{if(Read_BlockData(buff, 512))

                            buff += 512;

                        }while(--count);

                     SD_SendCmd( CMD12, 0, 1, respbuf);

              }

       }

       SPI_CS_SET();

       SPI_SendByte(0xff);

       return      RES_OK;

}

/*-----------------------------------------------------------------------*/

/* Write Sector(s)                                                       */

/*-----------------------------------------------------------------------*/

 

#if _READONLY == 0

DRESULT disk_write (

        BYTE drv,                    /* Physical drive nmuber (0) */

        const BYTE *buff, /* Pointer to the data to be written */

        DWORD sector,            /* Start sector number (LBA) */

        BYTE count                  /* Sector count (1..255) */

        )

{

    if (drv || !count) return RES_PARERR;

    if (Stat & STA_NOINIT) return RES_NOTRDY;

    if (Stat & STA_PROTECT) return RES_WRPRT;

 

       sector *= 512;

       if(count == 1)

       {

              if(SD_SendCmd( CMD24, sector, 1, respbuf) && Write_BlockData(buff, 0xfe))

              count = 1;

       }

       else

       {

              if(SD_SendCmd( CMD25, sector, 1, respbuf) == 1)

              do{

                     if(Write_BlockData(buff, 0xfe))    return  0;

                     buff += 512;

                 }while(--count);

              if(Write_BlockData(0, 0xfd) == 1)       count = 1;

       }

       SPI_CS_SET();

       SPI_SendByte(0xff);

       return      RES_OK;

}

#endif /* _READONLY == 0 */

 

/*-----------------------------------------------------------------------*/

/* get_fattime           本工程上没用到这个功能    */

/*-----------------------------------------------------------------------*/

 

DWORD get_fattime (void)

{

    return 0; 

}

 

/*-----------------------------------------------------------------------*/

/* Miscellaneous Functions                                               */

/*-----------------------------------------------------------------------*/

 

#if _USE_IOCTL != 0

DRESULT disk_ioctl (

        BYTE drv,             /* Physical drive nmuber (0) */

        BYTE ctrl,             /* Control code */

        void *buff             /* Buffer to send/receive control data */

        )

{

    DRESULT res;

    BYTE n, csd[16], *ptr = buff;

    WORD csize;

  

    if (drv) return RES_PARERR;

       res = RES_ERROR;

 

    if (ctrl == CTRL_POWER) {

        switch (*ptr) {

            case 0:           /* Sub control code == 0 (POWER_OFF) */

                   SD_POWER_OFF();             /* Power off */

                res = RES_OK;

                break;

            case 1:           /* Sub control code == 1 (POWER_ON) */

                SD_POWER_ON();                            /* Power on */

                res = RES_OK;

                break;

            case 2:           /* Sub control code == 2 (POWER_GET) */

                *(ptr+1) = 1;

                res = RES_OK;

                break;

            default :

                res = RES_PARERR;

        }

    }

       else{

              if (Stat & STA_NOINIT) return RES_NOTRDY;

              switch(ctrl){

                     case CTRL_SYNC :             SPI_CS_CLR(); SPI_SendByte(0xff);res = RES_OK;break;

                  case GET_SECTOR_SIZE :  *(WORD*)buff = 512;res = RES_OK; break;/* Get R/W sector size (WORD) */

            case MMC_GET_TYPE :          *ptr = 1; res = RES_OK;       break;/* Get card type flags (1 byte) */

            case GET_SECTOR_COUNT :  if(SD_SendCmd( CMD9, 0, 1, respbuf) && Read_BlockData(csd, 16))

                            { if ((csd[0] >> 6) == 1) {    /* SDC ver 2.00 */

                        csize = csd[9] + ((WORD)csd[8] << 8) + 1;

                        *(DWORD*)buff = (DWORD)csize << 10;

                    } else {                               /* SDC ver 1.XX or MMC*/

                        n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;

                        csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;

                        *(DWORD*)buff = (DWORD)csize << (n - 9);

                    }

                    res = RES_OK; }

                break;

            case GET_BLOCK_SIZE :  if(SD_SendCmd( CMD9, 0, 1, respbuf) && Read_BlockData(csd, 16))

                               *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1); 

                    res = RES_OK;

                            break;

                   case MMC_GET_CSD : if(SD_SendCmd( CMD9, 0, 1, respbuf) && Read_BlockData(csd, 16))   res = RES_OK;break;

                     case MMC_GET_CID :  if(SD_SendCmd( CMD10, 0, 1, respbuf) && Read_BlockData(csd, 16))  res = RES_OK;break;

                     case MMC_GET_OCR :  if(SD_SendCmd( CMD58, 0, 1, respbuf)){

                                for(n=4;n;n--) *ptr++ = SPI_SendByte(0xff);res = RES_OK;} break;

                     case MMC_GET_SDSTAT : if (SD_SendCmd( ACMD13, 0, 2, respbuf)) {      /* SD_STATUS */

                    SPI_SendByte(0xff);

                    if (Read_BlockData(ptr, 64))

                        res = RES_OK;

                }

                break;

 

            default:

                res = RES_PARERR;

                     }

              }

        SPI_CS_SET();

       SPI_SendByte(0xff);

       return      res;

}

#endif /* _USE_IOCTL != 0 */

结束!大家多多指教哦……

 

回复评论 (4)

补充一点,我使用的是LPC2132微控制器,呵呵
点赞  2010-7-16 18:55

回复 沙发 cuizhihao 的帖子

你可以参照我的LPC1114的程序,是一样的,可以直接移植过来!!!

https://bbs.eeworld.com.cn/thread-105572-3-1.html 工程在26楼!!!

[ 本帖最后由 zhaojun_xf 于 2010-7-17 08:32 编辑 ]
我的博客
点赞  2010-7-17 08:29
我最近也把它移植到LPC2132了,如果需要我可以传给你!
我的博客
点赞  2010-7-17 08:29

回复 4楼 zhaojun_xf 的帖子

那太谢谢啦,呵呵,我先看看……
点赞  2010-7-17 12:50
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复