当前位置: 代码迷 >> 综合 >> cubemx stm32 SDIO_DMA_FATFS基于SD卡的FATFS测试
  详细解决方案

cubemx stm32 SDIO_DMA_FATFS基于SD卡的FATFS测试

热度:60   发布时间:2024-02-23 12:57:54.0

一、遇到的问题:

1、刚开始挂载成功,f_open一直不行。
;后面发现新版cubemx FATFS->configuration->Platform Setting里有一个BSP设置函数,用来检测SD卡是否插入。
2、解决上面问题,发现还是不太行,后面就降低了频率。SDIOCLK clock divide factor设置为4。 SDIO DMA中断高于SDIO 中断。
3、加上上面问题后,f_open f_write f_read都可以,但是偶尔会出差;f_mkfs报错 FS_DISK_ERR,随后我加上了SDIO硬件流使能了
4、硬件流使能后,问题得到了全部解决。工件稳定,每次都可以执行成功。

二、配置与代码

cubemx版本是V5.6.0
固件:FW_F1V1.8.2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面新版本多了一个检测SD卡是否存在,但是目前很大都是没有这个引脚的,它是低电平有效。我用PG15管脚设置为下拉输入。让它一直处于低电平有效状态。如果不用一个管脚检测,也可以在代码里,修改始终返回SD_PRESENT:

__weak uint8_t BSP_SD_IsDetected(void)
{
    __IO uint8_t status = SD_PRESENT;// if (BSP_PlatformIsDetected() == 0x0) 
// {
    
// status = SD_NOT_PRESENT;
// }return status;
}

直接上代码,测试代码引用盘石的吧,省的写了

/* USER CODE BEGIN Header */
/********************************************************************************* @file : main.c* @brief : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:* www.st.com/SLA0044********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "rtc.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "rtc.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV */
FATFS fs;													/* FatFs文件系统对象 */
FIL file;													/* 文件对象 */
FRESULT f_res;                    /* 文件操作结果 */
UINT fnum;            					  /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={
    0};        /* 读缓冲区 */
BYTE WriteBuffer[]= "欢迎使用硬石STM32开发板 今天是个好日子,新建文件系统测试文件\n";/* 写缓冲区*//* 扩展变量 ------------------------------------------------------------------*/
/* 私有函数原形 --------------------------------------------------------------*/
static void printf_fatfs_error(FRESULT fresult);
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *f)
{
    #if 1HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1,0x10);#endifreturn ch;
}
/* USER CODE END 0 *//*** @brief The application entry point.* @retval int*/
int main(void)
{
    /* USER CODE BEGIN 1 */
#include "stdio.h"
#include "rtc.h"/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_SDIO_SD_Init();MX_RTC_Init();MX_USART1_UART_Init();MX_FATFS_Init();/* USER CODE BEGIN 2 */
printf("****** 即将进行测试... ******\r\n");	if(retSD == 0){
    //在SD卡挂载文件系统,文件系统挂载时会对SD卡初始化f_res = f_mount(&fs,(TCHAR const*)SDPath,1);printf_fatfs_error(f_res);/*----------------------- 格式化测试 ---------------------------*/  #if 0f_res = FR_NO_FILESYSTEM;#endif/* 如果没有文件系统就格式化创建创建文件系统 */if(f_res == FR_NO_FILESYSTEM){
    printf("》SD卡还没有文件系统,即将进行格式化...\r\n");/* 格式化 */f_res=f_mkfs((TCHAR const*)SDPath,0,0);							if(f_res == FR_OK){
    printf("》SD卡已成功格式化文件系统。\r\n");/* 格式化后,先取消挂载 */f_res = f_mount(NULL,(TCHAR const*)SDPath,1);			/* 重新挂载 */			f_res = f_mount(&fs,(TCHAR const*)SDPath,1);}else{
    printf("《《格式化失败。》》\r\n");while(1);}}else if(f_res!=FR_OK){
    printf("!!SD卡挂载文件系统失败。(%d)\r\n",f_res);printf_fatfs_error(f_res);while(1);}else{
    printf("》文件系统挂载成功,可以进行读写测试\r\n");}/*----------------------- 文件系统测试:写测试 -----------------------------*//* 打开文件,如果文件不存在则创建它 */printf("****** 即将进行文件写入测试... ******\r\n");	f_res = f_open(&file, "FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );if ( f_res == FR_OK ){
    printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n");/* 将指定存储区内容写入到文件内 */f_res=f_write(&file,WriteBuffer,sizeof(WriteBuffer),&fnum);if(f_res==FR_OK){
    printf("》文件写入成功,写入字节数据:%d\r\n",fnum);printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);}else{
    printf("!!文件写入失败:(%d)\r\n",f_res);}    /* 不再读写,关闭文件 */f_close(&file);}else{
    	printf("!!打开/创建文件失败。\r\n");}/*------------------- 文件系统测试:读测试 ------------------------------------*/printf("****** 即将进行文件读取测试... ******\r\n");f_res = f_open(&file, "FatFs读写测试文件.txt", FA_OPEN_EXISTING | FA_READ); 	 if(f_res == FR_OK){
    printf("》打开文件成功。\r\n");f_res = f_read(&file, ReadBuffer, sizeof(ReadBuffer), &fnum); if(f_res==FR_OK){
    printf("》文件读取成功,读到字节数据:%d\r\n",fnum);printf("》读取得的文件数据为:\r\n%s \r\n", ReadBuffer);	}else{
    printf("!!文件读取失败:(%d)\r\n",f_res);}		}else{
    printf("!!打开文件失败。\r\n");}/* 不再读写,关闭文件 */f_close(&file);/* 不再使用,取消挂载 */f_res = f_mount(NULL,(TCHAR const*)SDPath,1);	/* 注销一个FatFS设备:SD卡 */FATFS_UnLinkDriver(SDPath);}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){
    /* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {
    0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {
    0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {
    0};/** Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.LSIState = RCC_LSI_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){
    Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){
    Error_Handler();}PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK){
    Error_Handler();}
}/* USER CODE BEGIN 4 */
/*** 函数功能: FatFS文件系统操作结果信息处理.* 输入参数: FatFS文件系统操作结果:FRESULT* 返 回 值: 无* 说 明: 无*/
static void printf_fatfs_error(FRESULT fresult)
{
    switch(fresult){
    case FR_OK:                   //(0)printf("》操作成功。\r\n");break;case FR_DISK_ERR:             //(1)printf("!!硬件输入输出驱动出错。\r\n");break;case FR_INT_ERR:              //(2)printf("!!断言错误。\r\n");break;case FR_NOT_READY:            //(3)printf("!!物理设备无法工作。\r\n");break;case FR_NO_FILE:              //(4)printf("!!无法找到文件。\r\n");break;case FR_NO_PATH:              //(5)printf("!!无法找到路径。\r\n");break;case FR_INVALID_NAME:         //(6)printf("!!无效的路径名。\r\n");break;case FR_DENIED:               //(7)case FR_EXIST:                //(8)printf("!!拒绝访问。\r\n");break;case FR_INVALID_OBJECT:       //(9)printf("!!无效的文件或路径。\r\n");break;case FR_WRITE_PROTECTED:      //(10)printf("!!逻辑设备写保护。\r\n");break;case FR_INVALID_DRIVE:        //(11)printf("!!无效的逻辑设备。\r\n");break;case FR_NOT_ENABLED:          //(12)printf("!!无效的工作区。\r\n");break;case FR_NO_FILESYSTEM:        //(13)printf("!!无效的文件系统。\r\n");break;case FR_MKFS_ABORTED:         //(14)printf("!!因函数参数问题导致f_mkfs函数操作失败。\r\n");break;case FR_TIMEOUT:              //(15)printf("!!操作超时。\r\n");break;case FR_LOCKED:               //(16)printf("!!文件被保护。\r\n");break;case FR_NOT_ENOUGH_CORE:      //(17)printf("!!长文件名支持获取堆空间失败。\r\n");break;case FR_TOO_MANY_OPEN_FILES:  //(18)printf("!!打开太多文件。\r\n");break;case FR_INVALID_PARAMETER:    // (19)printf("!!参数无效。\r\n");break;}
}
/* USER CODE END 4 *//*** @brief Period elapsed callback in non blocking mode* @note This function is called when TIM4 interrupt took place, inside* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment* a global variable "uwTick" used as application time base.* @param htim : TIM handle* @retval None*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    /* USER CODE BEGIN Callback 0 *//* USER CODE END Callback 0 */if (htim->Instance == TIM4) {
    HAL_IncTick();}/* USER CODE BEGIN Callback 1 *//* USER CODE END Callback 1 */
}/*** @brief This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef USE_FULL_ASSERT
/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{
     /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/