本帖最后由 xld0932 于 2024-3-25 15:38 编辑
1.概述
国民N32A455系列MCU支持1路SDIO接口,安全数字输入输出接口(Secure Digital Input and Output),简称SDIO接口, SDIO主机接口为AHB外设总线和多媒体卡(MMC)、 SD存储卡、 SDIO卡设备间提供了操作接口。SDIO时钟速率可达48MHz。
2.原理图
3.SDIO示例程序
通过官方的示例程序“Nationstech.N32A455_Library.1.1.0\projects\n32a455_EVAL\examples\SDIO\uSDCard”,测试TF卡,通过示例程序读取TF卡数据,获取TF卡信息,运行结果如下所示:
4.移植FatFs文件系统
我们先将FatFs源文件解压并添加到工程中,然后配置头文件的包含路径:
然后我们对diskio.c接口文件进行移植,直接调试官方示例程序中的应用函数,需要注意的是官方示例程序默认是DMA方式,在操作缓存的时候需要注意哦,可以参考官方示例程序的写法,具体如下所示:
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
#include <stdio.h>
#include "sdio_sdcard.h"
#define diskio_BLOCK_SIZE 512
#pragma pack(4)
u32 diskio_Buffer_Block_Tx[diskio_BLOCK_SIZE / 4];
u32 diskio_Buffer_Block_Rx[diskio_BLOCK_SIZE / 4];
#pragma pack()
#define diskio_Buffer_Block_Tx ((uint8_t *)diskio_Buffer_Block_Tx)
#define diskio_Buffer_Block_Rx ((uint8_t *)diskio_Buffer_Block_Rx)
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
for (UINT i = 0; i < count; i++)
{
SD_ReadBlock(diskio_Buffer_Block_Rx, sector++, SDCardInfo.CardBlockSize);
SD_WaitReadOperation();
for (UINT j = 0; j < SDCardInfo.CardBlockSize; j++)
{
buff[i * 512 + j] = diskio_Buffer_Block_Rx[j];
}
}
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* 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 */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
for (UINT i = 0; i < count; i++)
{
for (UINT j = 0; j < SDCardInfo.CardBlockSize; j++)
{
diskio_Buffer_Block_Tx[j] = buff[i * 512 + j];
}
SD_WriteBlock(diskio_Buffer_Block_Tx, sector++, SDCardInfo.CardBlockSize);
SD_WaitWriteOperation();
}
return RES_OK;
}
#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 = RES_OK;
switch(cmd)
{
case CTRL_SYNC:
break;
case GET_SECTOR_COUNT:
*(WORD *)buff = SDCardInfo.CardCapacity / SDCardInfo.CardBlockSize;
break;
case GET_SECTOR_SIZE:
*(WORD *)buff = SDCardInfo.CardBlockSize;
break;
case GET_BLOCK_SIZE:
*(WORD *)buff = 1;
break;
default:
res = RES_PARERR;
break;
}
return res;
}
DWORD get_fattime(void)
{
DWORD ret_val = 0;
/* 2020-10-12 18:05:10 */
ret_val = (20 << 25)
+ (10 << 21)
+ (12 << 16)
+ (18 << 11)
+ (05 << 5)
+ (10 / 2);
return ret_val;
}
5.文件读写操作
在移植好FatFs文件系统后,我们就来编写一个文件系统的挂载、对文件的打开、关闭、读写这些基本操作的演示函数,如下所示:
#include <string.h>
#include "ff.h"
#include "diskio.h"
#include "ffconf.h"
void File_System_Initialize(void)
{
FATFS FatFs;
FIL File;
UINT br = 0, bw = 0;
FRESULT Result;
uint8_t Buffer[200];
memset(Buffer, 0, sizeof(Buffer));
Result = f_mount(&FatFs, "0:", 1);
if(Result)
{
printf("\r\nf_mount Fail! Result = %d\r\n", Result);
}
else
{
Result = f_open(&File, "0:/HELLO.TXT", FA_READ);
if(Result != RES_OK)
{
printf("\r\nf_open HELLO.txt Fail! Result = %d\r\n", Result);
}
else
{
do
{
Result = f_read(&File, Buffer, 200, &br);
if(br != 0) printf("\r\nf_read : %s\r\n", Buffer);
} while(br != 0);
f_close(&File);
}
Result = f_open(&File, "0:/TEST.TXT", FA_CREATE_ALWAYS | FA_WRITE);
if (Result != RES_OK)
{
printf("\r\nf_open TEST.txt Fail! Result = %d\r\n", Result);
}
else
{
Result = f_write(&File, "TEST...", 7, &bw);
if (Result != RES_OK)
{
printf("\r\nf_write TEST.txt Fail! Result = %d\r\n", Result);
}
else
{
printf("\r\nf_write TEST.txt Result = %d, bw = %d\r\n", Result, bw);
f_sync(&File);
}
f_close(&File);
}
}
}
6.运行结果
能够正确的读取到TF卡中文件的数据内容,以及创建新文件并写入相应内容,并返回正常的写入状态值,如下图所示:
7.附件