环境准备
硬件:AC781X demo板, SD卡,卡套
软件: Keil5.2.3
因为AC781X不支持SDIO,所以我们要采用SPI方式与SD卡通信,SPI有4线,加上电源线总共六根线,下图是我焊好的接线(千万不要直接在SD卡上焊,不然SD卡就焊废了)
1,首先从网上下载最新的FATFS文件系统源码http://elm-chan.org/fsw/ff/00index_e.html,本贴用的是R0.13c版本
2,新建一个keil工程,并在工程下新建一个FATfs文件夹,将下载的文件解压到该文件夹下
3,按官方的文档,我们只需要移植实现diskio.c中的函数即可;这里,我们需要实现diskio.c的底层操作,这里我用了两个文件,一个spi.c用于实现底层SPI的初始化和读写操作,一个sdcard.c用于实现对SD卡的操作封装。整体的工程框架如下:
这里将下diskio.c的一些修改部分:
/* Definitions of physical drive number for each drive */
#define DEV_SD 0 /* Example: Map SD/SD card to physical drive 1 */
#define DEV_RAM 1 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
文件默认设置了三种存储系统,SD,RAM以及USB,我们使用的是SD,为了方便操作,我们将SD改为物理驱动0;
接下来就是实现后面的几个函数了,按照官方对函数的说明,我们调用自己的程序,并将自己的值与FATfs的值进行转化:
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
//result = RAM_disk_status();
// translate the reslut code here
stat = STA_NODISK;
return stat;
case DEV_SD :
result = SD_disk_status();
// translate the reslut code here
if (result == 0)
{
stat = 0;
}
else
{
stat = STA_NODISK;
}
return stat;
case DEV_USB :
//result = USB_disk_status();
// translate the reslut code here
stat = STA_NODISK;
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
//result = RAM_disk_initialize();
// translate the reslut code here
stat = STA_NODISK;
return stat;
case DEV_SD :
result = SD_disk_initialize();
// translate the reslut code here
if (result == 0)
{
stat = 0;
}
else
{
stat = STA_NODISK;
}
return stat;
case DEV_USB :
//result = USB_disk_initialize();
// translate the reslut code here
stat = STA_NODISK;
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
//result = RAM_disk_read(buff, sector, count);
// translate the reslut code here
res = RES_ERROR;
return res;
case DEV_SD :
// translate the arguments here
result = SD_disk_read(buff, sector, count);
// translate the reslut code here
res = result==0?RES_OK:RES_ERROR;
return res;
case DEV_USB :
// translate the arguments here
//result = USB_disk_read(buff, sector, count);
// translate the reslut code here
res = RES_ERROR;
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if FF_FS_READONLY == 0
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
//result = RAM_disk_write(buff, sector, count);
// translate the reslut code here
res = RES_ERROR;
return res;
case DEV_SD :
// translate the arguments here
result = SD_disk_write(buff, sector, count);
// translate the reslut code here
if (result == 0)
{
res = RES_OK;
}
else
{
res = RES_ERROR;
}
return res;
case DEV_USB :
// translate the arguments here
//result = USB_disk_write(buff, sector, count);
// translate the reslut code here
res = RES_ERROR;
return res;
}
return RES_PARERR;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
switch (pdrv) {
case DEV_RAM :
// Process of the command for the RAM drive
return res;
case DEV_SD :
// Process of the command for the SD/SD card
switch(cmd)
{
case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_SIZE:
*(DWORD*)buff = g_sdCardInfo.sectorSize;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = g_sdCardInfo.blockSize;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = g_sdCardInfo.sectorCount;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
return res;
case DEV_USB :
// Process of the command the USB drive
return res;
}
return RES_PARERR;
}
实现完成后,我们就可以使用FATfs中的函数了,官网上对每一个API接口都有详细注释,部分函数还提供了使用示例,我们可以从官网的示例上找寻我们需要的代码:
while(SD_disk_initialize()!=0)//can not find SD card
{
mdelay(1000);
printf("Please Check! \r\n");
}
res = f_mount(&fs, "", 1);
if (FR_OK != res)
{
printf("\r\nfirst mount disk error : %02x, format disk\r\n", res);
res = f_mkfs("", FM_FAT32, 0, work, sizeof(work));
if (FR_OK != res)
{
printf("\r\nformat disk error : %02x\r\n", res);
return -1;
}
res = f_mount(&fs, "", 1);
if (FR_OK != res)
{
printf("\r\nmount disk error : %02x\r\n", res);
return -1;
}
}
printf("\r\nmount disk success\r\n");
strcpy(buff, "/");
res = scan_files(buff);
这里我自己先调用了SD_disk_initialize函数确保能找到SD卡(实测有时候总会检测不到,不知道是不是因为SD卡和卡套之间接触问题还是焊接问题,需要插拔一下SD卡才行)。
在检测到SD卡后调用f_mount函数挂载SD卡,如果失败了,表示SD卡没有格式化,则将SD卡先格式化,再重新挂载。这里实现了一个scan_files函数,可以遍历SD卡中的所有文件。这里就不在赘述。
最后附上实现代码:
FATFS_sample.rar
(1.96 MB)
|