stm32f1sdio移植fatfs

fatfs移植

  1. 上官网fatfs,最下面下载原码,之后解压。这里版本很重要,版本不同可能兼容就不一样。本人试了下ff14版本还不错,如果一个版本不行,可以再换个版本。多两个版本自然也就熟悉了。
  2. 将解压后的‘diskio.c’,‘ff.c’,‘ffsystem.c’,'ffunicode.c’加入项目。ff.h所在目录加入到项目搜索目录
  3. 更改diskio.c中的底层驱动

/*-----------------------------------------------------------------------*/
/* 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 "stm32f10x_conf.h"

// 这里的头文件不要忘记加入了

// 这里sdio会使用DEV_MMC这个逻辑卷号,如果还想加入spi_flash、USB。可以在这里加入
/* Definitions of physical drive number for each drive */
#define DEV_RAM		0	/* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC		1	/* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB		2	/* Example: Map USB MSD to physical drive 2 */


/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = STA_NOINIT;
	/*int result;*/
  SDTransferState card_state = SD_TRANSFER_OK;

	switch (pdrv) {
	case DEV_RAM :
		// translate the reslut code here

		return stat;

	case DEV_MMC :
		// 这里是SDIO状态
    card_state = SD_GetStatus();
    if(card_state == SD_TRANSFER_ERROR)
      stat = RES_ERROR;
    else if(card_state == SD_TRANSFER_BUSY)
      stat = RES_NOTRDY;
    else
      stat = RES_OK;

		return stat;

	case DEV_USB :
		// translate the reslut code here

		return stat;
	}
	return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

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

	switch (pdrv) {
	case DEV_RAM :
		// translate the reslut code here

		return stat;

	case DEV_MMC :
		// SDIO 初始化
    if(SD_OK == SD_Init())
      stat = RES_OK;

		return stat;

	case DEV_USB :
		// translate the reslut code here

		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 */
	LBA_t sector,	/* Start sector in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res = RES_PARERR;

	switch (pdrv) {
	case DEV_RAM :
		// translate the reslut code here

		return res;

	case DEV_MMC :
		// 数据读取
    if(count > 1){
      SD_ReadMultiBlocks(buff, sector * BLOCK_SIZE, BLOCK_SIZE, count);
      SD_WaitReadOperation();
      while(SD_GetState() != SD_TRANSFER_OK);
    }
    else{
      SD_ReadBlock(buff, sector * BLOCK_SIZE, BLOCK_SIZE);
      SD_WaitReadOperation();
      while(SD_GetState() != SD_TRANSFER_OK);
    }

    res = RES_OK;

		return res;

	case DEV_USB :
		// translate the reslut code here

		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 */
	LBA_t sector,		/* Start sector in LBA */
	UINT count			/* Number of sectors to write */
)
{
	DRESULT res = RES_PARERR;

	switch (pdrv) {
	case DEV_RAM :
		// translate the reslut code here

		return res;

	case DEV_MMC :
		// 数据写入
    if(count > 1){
      SD_WriteMultiBlocks((uint8_t)buff, sector * BLOCK_SIZE, BLOCK_SIZE, count);
      SD_WaitWriteOperation();
      while(SD_GetState() != SD_TRANSFER_OK);
    }
    else{
      SD_WriteBlock((uint8_t)buff, sector * BLOCK_SIZE, BLOCK_SIZE);
      SD_WaitWriteOperation();
      while(SD_GetState() != SD_TRANSFER_OK);
    }
    res = RES_OK;

		return res;

	case DEV_USB :
		// translate the reslut code here

		return res;
	}

	return RES_PARERR;
}

#endif


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/
// 这个有的版本设置后不会用到,但在FF_MIN_SS不是512时会用到
DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res = RES_PARERR;

	switch (pdrv) {
	case DEV_RAM :

		// Process of the command for the RAM drive

		return res;

	case DEV_MMC :

		// Process of the command for the MMC/SD card
    switch(cmd){
			case GET_SECTOR_COUNT:
				*(DWORD *)buff = 1;
				return RES_OK;
			case GET_SECTOR_SIZE:
				*(DWORD *)buff = 512;
				return RES_OK;
			case GET_BLOCK_SIZE:
				*(DWORD *)buff = 1;
				return RES_OK;
			case CTRL_SYNC:
				return RES_OK;
		}

		return res;

	case DEV_USB :

		// Process of the command the USB drive

		return res;
	}

	return RES_PARERR;
}


/*-----------------------------------------------------------------------*/
/* Get Current time                                                      */
/*-----------------------------------------------------------------------*/
// 时间全返回0
DWORD get_fattime(void){
  return 0;
}

  1. 设置ffconf.h,使之支持中文

// 格式化打开
#define FF_USE_MKFS		1
// seek也打开
#define FF_USE_FASTSEEK	1
// 简体中文
#define FF_CODE_PAGE  936
// 这里可以先设置为0,然后试下2
#define FF_USE_LFN    2
// 最多打开10个卷标,这里不设置,如果想用1的卷标就会报错,只能使用0做为唯一的卷标
#define FF_VOLUMES		10
// 下面这两个要检查下,如果不是512很可能就会调用disk_ioctl。如果没有实现disk_ioctl就有可能会报错
#define FF_MIN_SS		512
#define FF_MAX_SS		512
  1. main.c中加入测试代码
// 因为本人使用的freeRTOS,因此将测试代码放在一个任务里面。如果你没有用实时系统,可以直接放在一个测试函数里面
void fatfs_test_task(void *pvParameter)
{
  int res;
  int a;

  FIL fdst;
  FATFS fs;
  UINT br, bw;
  BYTE buffer[512];
  BYTE textFileBuffer[] = "think you for use fatfs~ ^ _ ^ \r\n";

  // 这里的挂载函数不同版本不一样,这个格式是较新的版本
	res = f_mount(&fs, "1:", 1);
  // 旧些的版本使用以下形式
  // res = f_mount(1, &fs);
  res = f_open(&fdst, "1:/Demo.TXT", FA_WRITE | FA_CREATE_ALWAYS);

  // 下面是写入测试
  if(res == FR_OK){
    res = f_write(&fdst, textFileBuffer, sizeof(textFileBuffer), &bw);
		f_close(&fdst);
    printf("\r\n file create success");
		printf("\r\n write date %d", bw);
  }
  else if( res == FR_EXIST){
    printf("\r\n file exists\r\n");
  }

  // 下面是读取测试
  res = f_open(&fdst, "1:/Demo.TXT", FA_OPEN_EXISTING | FA_READ);
  br = 1;
  a = 0;
  for(;;){
    for(a = 0; a < 512; a++)
      buffer[a] = 0;

    res = f_read(&fdst, buffer, sizeof(buffer), &br);
    printf("\r\n %s ",buffer);
    if(res || br == 0) break;
  }
  f_close(&fdst);

  while(1);

}

  1. 编译一下,确认没有错误
  2. 将SD卡连上电脑,格式化为fat32。因为之前打开了格式化选择,也可以使用开发板格式化f_mkfs。读者有兴趣可以自己试下
  3. 可以先用调试模式看下。在f_mount打个断点,单步运行。每次返回0表示正确。如果不是返回0,可以看下FRESULT定义的枚举类型,表示什么错误。FR_DISK_ERR,FR_INT_ERR,FR_NO_FILESYSTEM几个错误是最常见的。DISK_ERR表示硬件错误,FR_INT_ERR是SD卡初始化错误,可以在diskio.c的初始化代码中打个断点,确认是否成功初始化,FR_NO_FILESYSTEM表示当前sd卡文件格式不是fat32或不能识别,请重新格式化。

搞定后,用串口助手连接电脑和开发板,如果显示以下信息,表示fatfs移植成功。此时将sd卡插入电脑,可以看到卡里面会有一个Demo.TXT的文件,里面有一行文字think you for use fatfs~ ^ _ ^

 file create success
 write date 34
 think you for use fatfs~ ^ _ ^ 

That is all

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值