使用STM32Cube在STM32F7开发板上实现SD+Freertos+Fatfs

简介

最近项目中可能需要使用到SD卡,所以需要对SD卡的配置和使用调研,在配置过程中遇到了一些问题,在此记录一下。

STM32Cube配置

  • Pinout
    这里写图片描述
    这里写图片描述
    只需要注意绿色部分的设定

  • Clock配置
    这里写图片描述
    这里使用了最大的Clock,SDMMC1的时钟是48MHz

  • FATFS配置
    这里写图片描述

  • Freertos配置
    这里写图片描述
    这里增大了Heap size,使用了heap_4的内存管理方式。

  • SD卡配置
    这里写图片描述
    这里写图片描述
    在这里打开SD的全局中断,并使用DMA2的方式传输数据

  • NVIC配置
    这里写图片描述
    SD的全局中断配置为5,DMA中断配置为6,5的优先级更高。

  • 工程配置
    这里写图片描述
    这里写图片描述

以上就是所有的配置内容了,配置完成后,直接使用Code generate功能就能自动生成keil工程。

代码修改

  • 初始化SD卡
    我生成的工程中需要手动添加BSP_SD_Init()函数,我是在MX_FATFS_Init()之前添加的。
/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
  BSP_SD_Init();
  /* init code for FATFS */
  MX_FATFS_Init();

  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    MX_FATFS_Run();
    vTaskDelay( 5000 );
  }
  /* USER CODE END StartDefaultTask */
}
  • 添加DMA中断处理函数
    stm32f7xx_it.c文件中,需要添加下面两个中断处理函数:
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
  BSP_SD_WriteCpltCallback();
}

void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
  BSP_SD_ReadCpltCallback();
}
  • 创建Queue
    在自动生成的Demo中,使用了SDQueueID这个Queue,但并没有自动创建它,所以需要手动创建一下。我是在SD_initialize()这个函数中创建的,具体创建的地方可能需要再仔细考虑清楚。

    DSTATUS SD_initialize(BYTE lun)
    {
      osMessageQDef(myQueueSD, QUEUE_SIZE, uint8_t*);
      SDQueueID = osMessageCreate(osMessageQ(myQueueSD), NULL);
      return SD_CheckStatus(lun);
    }
  • 将Pin的配置改为上拉
    在默认配置函数中HAL_SD_MspInit()对SDIO的Pin的默认配置是GPIO_NOPULL,但我在使用过程中发现,程序会卡死在SD_FindSCR()函数的以下这段代码中:

  /*卡在这个循环中出不去*/
  while(!__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DBCKEND))
  {
    if(__HAL_SD_GET_FLAG(hsd, SDMMC_FLAG_RXDAVL))
    {
      *(tempscr + index) = SDMMC_ReadFIFO(hsd->Instance);
      index++;
    }
    
    if((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
    {
      return HAL_SD_ERROR_TIMEOUT;
    }
  }

后面我将GPIO改为GPIO_PULLUP后解决了这个问题,具体原因暂时还不清楚。

    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
                          |GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;//GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

简单Fatfs应用

void StartDefaultTask(void const * argument)
{
    BSP_SD_Init();
  /* init code for FATFS */
  MX_FATFS_Init();

  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */

  for(;;)
  {
    /*自己实现一个Run方法,每隔5秒往SD卡中的文件写入数据*/
    MX_FATFS_Run();
    vTaskDelay( 5000 );
  }
  /* USER CODE END StartDefaultTask */
}

void MX_FATFS_Init(void) 
{
  /*## FatFS: Link the SD driver ###########################*/
  retSD = FATFS_LinkDriver(&SD_Driver, SDPath);

  /* USER CODE BEGIN Init */
  /* 在Init的时候挂载文件系统 */     
  if(f_mount(&SDFatFS, SDPath,0) != FR_OK)  
  {  
    while(1);
  }   
  /* USER CODE END Init */
}

void MX_FATFS_Run(void)
{
  UINT writeBytes;
  /*文件系统基本操作:打开文件,定位到文件结尾,写入内容,关闭文件*/
  if(f_open(&SDFile, "SDTest.txt", FA_READ|FA_WRITE|FA_OPEN_ALWAYS) != FR_OK)
  {
    while(1);
  }
  if(f_lseek(&SDFile, f_size(&SDFile)) != FR_OK)
  {
    while(1);
  }
  if(f_write(&SDFile, "sd Loop", sizeof("sd Loop"), &writeBytes) != FR_OK)
  {
    while(1);
  }
  if(f_close(&SDFile) != FR_OK)
  {
    while(1);
  } 
}
  • SD写入结果:
    这里写图片描述

猜你喜欢

转载自www.cnblogs.com/xw-kaka/p/9068846.html
今日推荐