1. 程式人生 > >使用STM32CUBEMX生成USB Mass Storage程式碼,通過SDIO讀寫TF卡

使用STM32CUBEMX生成USB Mass Storage程式碼,通過SDIO讀寫TF卡

首先配置USB為Mass Storage Class,配置SDIO為 SD 4 bits wide bus。


這裡我使用了FreeRTOS和FATFS,用不用和本例無關。有一個坑,就是SDIO的配置介面,MX軟體建議不設分頻,但這裡需要慎重,SDIOCLK的分頻要按照自己硬體板子的情況設定,我用的某型號開發板,如果用最高頻率,會出現TF卡讀寫不穩定,設定一下分頻才好。

設定完畢,生成程式碼和工程。開啟工程,在usbd_storage_if.c檔案裡配置TF卡(SD卡)的基本IO操作。

在檔案開頭加入

#define BLOCK_SIZE                       512

extern SD_HandleTypeDef hsd;
extern HAL_SD_CardInfoTypedef SDCardInfo;

注意!上面這三行就算寫到USER CODE BEGIN... 和USER CODE END...的保護區裡MX重新生成貌似也會被自動抹掉。

填充如下函式

int8_t STORAGE_GetCapacity_FS (uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */   
  HAL_SD_Get_CardInfo(&hsd, &SDCardInfo);
  *block_num  = SDCardInfo.CardCapacity / BLOCK_SIZE;
  *block_size = BLOCK_SIZE;
  return (USBD_OK);
  /* USER CODE END 3 */ 
}

int8_t STORAGE_Read_FS (uint8_t lun, 
                        uint8_t *buf, 
                        uint32_t blk_addr,                       
                        uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
  HAL_SD_ReadBlocks(&hsd, (uint32_t*)buf, (uint64_t)(blk_addr * BLOCK_SIZE), BLOCK_SIZE, blk_len);
  return (USBD_OK);
  /* USER CODE END 6 */ 
}

int8_t STORAGE_Write_FS (uint8_t lun, 
                         uint8_t *buf, 
                         uint32_t blk_addr,
                         uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */ 
  HAL_SD_WriteBlocks(&hsd, (uint32_t*)buf, (uint64_t)(blk_addr * BLOCK_SIZE), BLOCK_SIZE, blk_len);
  return (USBD_OK);
  /* USER CODE END 7 */ 
}


還有一個需要注意的,就是生成的程式碼中sdio.c檔案裡有個問題需要手工改

void MX_SDIO_SD_Init(void)
{

  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;
  hsd.Init.ClockDiv = 2;

}

這裡的

hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;
這句話生成出來的時候是disable的(然而在MX的圖形介面中並沒有發現怎麼配置這段話),要人工改成enable,否則讀寫會不穩定。另,每一次MX重新生成,這裡的enable又會被自動的改回去,老坑爹了。

到此,所有配置完成。

最後說下MX的另一個bug,就是使用FreeRTOS的時候HAL_Delay函式無法使用,最後發現原因是 stm32f1xx_it.c 檔案中的SysTick_Handler
只加入了osSystickHandler()沒加入HAL_IncTick(),把後者加入就好了。

MX的bug比教程還多。。。ST的攻城獅們可長點心吧。。。