「弱小和无知不是生存的障碍,傲慢才是」|

shumei52

园龄:1年7个月粉丝:6关注:1

SD卡-fatfs文件系统移植

此篇文章在2022年12月31日被记录

FATFS文件系统移植

上文中完成了sd卡的驱动代码,本文陈述如何系统移植文件系统

源码下载

源码可以登录fatfs官网下载:http://elm-chan.org/fsw/ff/archives.html 我这里下载最新版本的源码包,下载完成后解压到本地大致浏览源码包的文件结构,主目录下有documents与source两个文件夹,其中documents中教会用户如何使用fatfs,source中主要包含三部分代码:

  • 物理层接口:diskio.c/diskio.h
  • fatfs源码:ff.c/ff.h
  • fatfs配置文件:ffconf.h
  • 操作系统扩展功能:ffsystem.c
  • 语言编码表:ffunicode.c
    我移植时的需求:不使用操作系统,编码语言使用英文,所以我只用到diskio.c/diskio.h、ff.c/ff.h、ffconf.h这五个文件,并将其添加到自己的工程中

接口绑定

上文中我们完成了sd卡的驱动代码,预留了如下几个接口:

uint8_t SD_WaitReady(void);
uint8_t SD_Init(void);
uint32_t SD_GetSectorCount(void);
uint8_t SD_ReadDisk(uint8_t*buf,uint32_t sector,uint8_t cnt);
uint8_t SD_WriteDisk(const uint8_t*buf,uint32_t sector,uint8_t cnt);

我们将其与diskio.c中的接口文件绑定:
首先需要新建一个我们自己的设备并删除掉代码中的示例设备:
#define DEV_SD 0
在获取磁盘状态的代码中新增我们的设备代码(这里我让我的设备状态无论如何返回OK):

DSTATUS disk_status (
	BYTE pdrv
)
{
	DSTATUS stat;
	int result;

	switch (pdrv) {
	case DEV_SD :
		stat = RES_OK;
	return stat;
	}
	return STA_NOINIT;
}

在磁盘初始化代码中绑定我们的SD卡初始化代码:

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat;
	int result;

	switch (pdrv) {
	case DEV_SD :
		result = SD_Init();
		if(0 == result)
		{
			stat = RES_OK;
		}
		return stat;
	}
	return STA_NOINIT;
}

在设备读扇区接口中绑定我们的读sd卡设备代码:

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 */
)
{
	DRESULT res;
	int result;

	switch (pdrv) {
		case DEV_SD :

		result = SD_ReadDisk(buff, sector, count);

		if(0 == result)
		{
			res = RES_OK;
		}

		return res;
	}

	return RES_PARERR;
}

在设备写数据接口中绑定我们的写sd卡数据代码:

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 */
)
{
	DRESULT res;
	int result;

	switch (pdrv) {
		case DEV_SD :

		result = SD_WriteDisk(buff, sector, count);

		if(0 == result)
		{
			res = RES_OK;
		}

		return res;
	}

	return RES_PARERR;
}

在设备状态获取接口中返回我们的设备状态代码:

这里总共获取设备的四种状态:

  • 设备是否就绪
  • 设备的扇区数量,取决于内存卡多大
  • 设备的块大小-恒定512
  • 设备的扇区大小-恒定512
DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res;
	int result;

	switch (pdrv) {
	case DEV_SD :
	switch (cmd) {
		case CTRL_SYNC: 
		if(0 == SD_WaitReady())
		{
			return RES_OK;
		}
		else
		{
			printf("not ready\r\n");
			return RES_NOTRDY;
		}
		case GET_SECTOR_COUNT: *(DWORD * )buff  = SD_GetSectorCount();return RES_OK;
		case GET_SECTOR_SIZE: *(DWORD * )buff  = 512 ;return RES_OK;
		case GET_BLOCK_SIZE: *(WORD * )buff = 512 ;return RES_OK;
	}
		return res;
	}
	return RES_PARERR;
}

fatfs配置

FF_FS_READONLY -是否开启只读功能
FF_FS_MINIMIZE -是否裁剪功能
FF_USE_FIND -是否开启文件寻找功能
FF_USE_MKFS -是否开启格式化功能(重要)
FF_FS_NORTC -关闭RTC功能(如果使用rtc则需要实现获取时间的接口)
FF_CODE_PAGE -使用哪种编码语言
详细的配置说明可以查看官网文档

文件系统demo测试

以上完成fatfs的移植,我们就可以在单片机上对SD卡实现PC端一样的文件操作,详细的接口使用还是去看官方文档,我实现了一个demo,挂载sd卡,如果未成功挂载SD卡就将其格式化,然后读取sd卡中的test.jpg,并拷贝一份重命名为copy.jpg:

uint8_t stat;
  stat=f_mount(&fs,"0:",1);//SD卡挂载
  printf("f_mount:%d\r\n",stat);
  if(stat!=FR_OK)
  {
    printf("f_mkfs :FAT32\r\n");
    stat = f_mkfs("0:", 0,(void*)f_mkfs_buff,sizeof(f_mkfs_buff));
    if(stat!=FR_OK)
    {
        printf("f_mkfs failed\r\n");
    }
    else
    {
        printf("f_mkfs successed\r\n");
    }
  }
  else
  {
    printf("SD Card init successed\r\n");
  }

  FIL fp;
	FRESULT res;
  UINT bw;
  UINT br;
  res=f_open(&fp,"0:/test.jpg",FA_READ);
  printf("read test.jpg:%d\r\n",res);

  uint32_t size = fp.obj.objsize;
  printf("test.jpg size is :%d\r\n",size);

  char *data = (char *)malloc(size);
  res=f_read(&fp,data,size,&br);
  f_close(&fp);

  res=f_open(&fp,"0:/copy.jpg",FA_READ|FA_WRITE|FA_CREATE_ALWAYS);
  if(res==FR_OK)
  {
    printf("creat copy.jpg\r\n");
    res=f_write(&fp,data,size,&bw);
    if(res==FR_OK)
    {
      printf("write copy.jpg\r\n");
    }
  }
  else
  {
    printf("error :%d\r\n",res);
  }
  f_close(&fp);
  
  free(data);
  printf("over \r\n");

最终再将内存卡插在电脑上可以发现存在被拷贝的图片(为什么是大写名称我也不知道,可能遗漏了某些东西):

img

其他可能存在的坑:为了保证格式化为FAT32格式,可是又懒滴写配置文件,在f_mkfs源码中修改默认的格式化类型为FAT32格式,这样可以实现windows系统更快的识别内存卡:
static const MKFS_PARM defopt = {FM_FAT32, 0, 0, 0, 0};

本文作者:shumei52

本文链接:https://www.cnblogs.com/shumei52/p/18599795

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   shumei52  阅读(28)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起