STM32使用HAL库驱动EMMC挂载FATFS文件系统


工程需要使用EMMC挂载FATFS文件系统,苦苦寻找皆为SD卡挂载FATFS,虽原理一样还是写了这么一篇博客,希望对新手可以有些帮助!!!

STM32驱动EMMC

使用STM32CubeMX配置SDIO

  1. 选择SDIO选项
    在这里插入图片描述
  2. 配置DMA
    在这里插入图片描述
  3. 选择中断优先级
    在这里插入图片描述

编写EMMC驱动

等待EMMC就绪

uint8_t WaitEMMCReady(void)
{
	uint8_t count = EMMC_TIMEOUT;
	while(count--)
	{
		if(HAL_MMC_GetCardState(&hmmc)== HAL_MMC_CARD_TRANSFER)
		{
			return HAL_OK;
		}
		HAL_Delay(1);
	}
	return HAL_ERROR;
}

EMMC读取n(n>=1)块

HAL_StatusTypeDef EMMC_ReadBlock_DMA(uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
{
	HAL_StatusTypeDef Status =  HAL_OK;
	if(WaitEMMCReady() != HAL_OK)
	{
		Status = HAL_BUSY;
	}
   HAL_DMA_DeInit(&hdma_sdio);
   hdma_sdio.Instance = DMA2_Channel4;
   hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
   hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
   hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
   hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
   hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
   hdma_sdio.Init.Mode = DMA_NORMAL;
   hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
   if(HAL_DMA_Init(&hdma_sdio) != HAL_OK)
   {
       Error_Handler();
   }

  __HAL_LINKDMA(&hmmc, hdmarx, hdma_sdio);
	if(HAL_MMC_ReadBlocks_DMA(&hmmc, pData, BlockAdd, NumberOfBlocks) != HAL_OK)
  {
     Status = HAL_ERROR;
  } 
   return Status; 
}

EMMC写入n(n>=1)块

HAL_StatusTypeDef EMMC_WriteBlock_DMA(uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
{
	HAL_StatusTypeDef Status =  HAL_OK;
  if(WaitEMMCReady() != HAL_OK)
	{
		Status = HAL_BUSY;
	}
    HAL_DMA_DeInit(&hdma_sdio);
   hdma_sdio.Instance = DMA2_Channel4;
   hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
   hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
   hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
   hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
   hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
   hdma_sdio.Init.Mode = DMA_NORMAL;
   hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
   if(HAL_DMA_Init(&hdma_sdio) != HAL_OK)
   {
       Error_Handler();
   }

   __HAL_LINKDMA(&hmmc, hdmatx, hdma_sdio);
  if (HAL_MMC_WriteBlocks_DMA(&hmmc, pData, BlockAdd, NumberOfBlocks) != HAL_OK)
  {

    Status = HAL_ERROR;
  }
  return Status; 
}

EMMC测试

  	uint8_t recvbuf[512];
  	uint8_t sendbuf[512] = {0xAA,0xBB,0xCC,0xDD};
	printf("\r\n--------> EMMC DMA Test\r\n");
	ret= EMMC_ReadBlock_DMA(recvbuf,0,1);
	if(ret == HAL_OK)
	{
		for (uint16_t i = 0; i < BLOCKSIZE; i++)
    {
      printf("0x%02x ",recvbuf[i]);
      if((i%16) == 0)
      {
        printf("\r\n");
      }
    }
	}
	ret = EMMC_WriteBlock_DMA(sendbuf,0,1);
	if(ret == HAL_OK)
	{
		printf("\r\n--------> EMMC 写入成功\r\n");
	}
  ret =  EMMC_ReadBlock_DMA(recvbuf,0,1);
	printf("\r\n--------> ret:%d\r\n",ret);
  if(ret == HAL_OK)
  {
    for (uint16_t i = 0; i < hmmc.MmcCard.BlockSize; i++)
    {
      printf("0x%02x ",recvbuf[i]);
      if((i%16) == 0)
      {
        printf("\r\n");
      }
    }
  }

移植FATFS文件系统

准备工作

1.FATFS官网下载地址:http://elm-chan.org/fsw/ff/00index_e.html
2.截至2024.6.1最新版本为0.15
3.本工程使用版本为0.11a

keil工程文件结构

在这里插入图片描述

修改底层驱动文件

底层驱动只需要修改diskio.c与ffconf.h

修改ffconf.h

#define _USE_MKFS 1 // 0–>1
#define _CODE_PAGE 936 //932–>936 日文到中文
#define _USE_LFN 1 // 0->1 支持长文件名
#define _VOLUMES 1 //根据你使用的盘符数 自行更改
#define _MAX_SS 4096 // 512–>4096 SPI 扇区大小为4096
#define _FS_LOCK 3 // 0–>3 支持同时打开文件数 3个

添加底层驱动

disk_status
DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = STA_NOINIT;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_status EMMC\r\n");
		stat &= ~STA_NOINIT;
	}
	return stat;
}
disk_initialize
DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = STA_NOINIT;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_initialize EMMC\r\n");
		if(HAL_MMC_Init(&hmmc)==HAL_OK)
		{
			printf("\r\n--------> disk_initialize EMMC Success\r\n");
			stat &= ~STA_NOINIT;
		}
	}
	return stat;
}

disk_read
DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_read EMMC\r\n");
		if(EMMC_ReadBlock_DMA((uint8_t*)buff,(uint32_t)sector,count) == HAL_OK)
		{
			printf("\r\n--------> disk_read Success\r\n");
			res = RES_OK;
		}
		else
		{
			res = RES_PARERR;
		}
	}
	else
	{
		res = RES_ERROR;
	}
	return res;
}
disk_write
DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address in LBA */
	UINT count			/* Number of sectors to write */
)
{
	DRESULT res;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_write EMMC\r\n");
		if(EMMC_WriteBlock_DMA((uint8_t*)buff,(uint32_t)sector,count) == HAL_OK)
		{
			printf("\r\n--------> disk_write Success\r\n");
			res = RES_OK;
		}
		else
		{
			res = RES_WRPRT;
		}
		
	}
	else
	{
		res = RES_ERROR;
	}
	return res;
}
disk_ioctl
DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res = STA_NOINIT;
	int result;
	if(pdrv == MMC)
	{
		printf("\r\n--------> disk_ioctl EMMC\r\n");
		switch(cmd)
		{
			case GET_SECTOR_COUNT:
				*(DWORD * )buff = hmmc.MmcCard.BlockNbr;
				break;
			case GET_SECTOR_SIZE:
				*(DWORD * )buff = hmmc.MmcCard.BlockSize;
				break;
			case GET_BLOCK_SIZE:
				*(DWORD * )buff = 1;
				break;
			case MMC_GET_SDSTAT:
				*(DWORD * )buff = HAL_MMC_GetState(&hmmc);
				break;
		}
		res = RES_OK;
	}
	return RES_OK;
}

FATFS文件挂载测试

FATFS fs;													/* FatFs文件系统对象 */
FIL fnew;													/* 文件对象 */
FRESULT res_sd;                /* 文件操作结果 */
UINT fnum;            					  /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0};        /* 读缓冲区 */
BYTE WriteBuffer[] = "Hello World!!!";         /* 写缓冲区*/
  printf("\r\n--------> EMMC 文件系统\r\n");
	res_sd = f_mount(&fs,"0:",1);
	
/*----------------------- 格式化测试 ---------------------------*/  
	/* 如果没有文件系统就格式化创建创建文件系统 */
	if(res_sd == FR_NO_FILESYSTEM)
	{
		printf("--------> EMMC还没有文件系统,即将进行格式化...\r\n");
    /* 格式化 */
		res_sd=f_mkfs("0:",0,0);							
		
		if(res_sd == FR_OK)
		{
			printf("--------> EMMC已成功格式化文件系统。\r\n");
      /* 格式化后,先取消挂载 */
			res_sd = f_mount(NULL,"0:",1);			
      /* 重新挂载	*/			
			res_sd = f_mount(&fs,"0:",1);
		}
		else
		{
			printf("--------> EMMC格式化失败\r\n");
			while(1);
		}
	}
  else if(res_sd!=FR_OK)
  {
    printf("--------> EMMC挂载文件系统失败:(%d)\r\n",res_sd);
    printf("--------> EMMC初始化不成功。\r\n");
		while(1);
  }
  else
  {
    printf("--------> EMMC文件系统挂载成功,可以进行读写测试\r\n");
  }
	printf("\r\n--------> EMMC即将进行文件写入\r\n");
	res_sd = f_open(&fnew, "0:FatFs1.txt",FA_CREATE_ALWAYS | FA_WRITE ); //ps:文件名不要过长,过长会导致创建失败,若过长需要在ffconf.h中开启宏定义
	if ( res_sd == FR_OK )
	{
		printf("--------> EMMC打开/创建FatFs1.txt文件成功,向文件写入数据。\r\n");
    /* 将指定存储区内容写入到文件内 */
		res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
    if(res_sd==FR_OK)
    {
      printf("--------> EMMC文件写入成功,写入字节数据:%d\n",fnum);
      printf("--------> EMMC向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
    }
    else
    {
      printf("-------->EMMC文件写入失败:(%d)\n",res_sd);
    }    
		/* 不再读写,关闭文件 */
    f_close(&fnew);
	}
	else
	{	
		printf("--------> EMMC打开/创建文件失败\r\n");
	}
	
	printf("--------> EMMC即将进行文件读取\r\n");
	res_sd = f_open(&fnew, "0:FatFs1.txt", FA_OPEN_EXISTING | FA_READ); 	 
	if(res_sd == FR_OK)
	{
		printf("--------> EMMC打开文件成功。\r\n");
		res_sd = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum); 
    if(res_sd==FR_OK)
    {
      printf("--------> EMMC文件读取成功,读到字节数据:%d\r\n",fnum);
      printf("--------> EMMC读取得的文件数据为:\r\n%s \r\n", ReadBuffer);	
    }
    else
    {
      printf("--------> EMMC文件读取失败:(%d)\n",res_sd);
    }		
	}
	else
	{
		printf("--------> EMMC打开文件失败\r\n");
	}
	/* 不再读写,关闭文件 */
	f_close(&fnew);	
  
	/* 不再使用文件系统,取消挂载文件系统 */
	f_mount(NULL,"0:",1);

###测试结果
在这里插入图片描述

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F1HAL库是STMicroelectronics公司为STM32F1系列微控制器提供的一种驱动库。而OLED(Organic Light Emitting Diode,有机发光二极管)是一种显示技术,借助有机材料的发光特性来实现显示效果。下面将简单介绍如何使用STM32F1HAL库驱动OLED。 首先,需要在STM32CubeMX中配置GPIO引脚和系统时钟,以便与OLED进行通信。然后,在工程中添加STM32F1HAL库文件,并在代码中引用相关的头文件。 接下来,按照OLED的通信协议(通常是I2C或SPI)来设置STM32F1的相应外设。如果选择使用I2C通信,则需要初始化I2C外设,并配置相应的GPIO引脚用于I2C通信。如果选择使用SPI通信,则需要初始化SPI外设,并配置相应的GPIO引脚用于SPI通信。 完成外设的设置后,就可以使用STM32F1HAL库提供的函数来控制OLED的显示。这些函数包括初始化OLED、设置显示的起始位置、写入需要显示的数据等。通过调用这些函数,可以实现对OLED的控制和显示。 需要注意的是,由于不同的OLED可能具有不同的通信协议和命令集,因此需要根据具体的OLED规格书或数据手册来编写相应的驱动程序。可以根据OLED的命令集来调用STM32F1HAL库提供的相应函数,以实现对OLED的操作。 综上所述,使用STM32F1HAL库驱动OLED,需要进行外设的配置和初始化,并调用相应的函数来控制OLED的显示。了解OLED的通信协议和命令集,根据具体的OLED规格书来编写相应的驱动程序是实现成功的关键。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值