打印
[应用相关]

使用STM32CUBEMX生成USB Mass Storage代码,通过SDIO读写TF卡

[复制链接]
1077|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangjiahao88|  楼主 | 2018-9-19 10:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用STM32CUBEMX生成USB Mass Storage代码,通过SDIO读写TF卡
沙发
wangjiahao88|  楼主 | 2018-9-19 10:27 | 只看该作者
首先配置USB为Mass Storage Class,配置SDIO为 SD 4 bits wide bus。

使用特权

评论回复
板凳
wangjiahao88|  楼主 | 2018-9-19 10:27 | 只看该作者
这里我使用了FreeRTOS和FATFS,用不用和本例无关。有一个坑,就是SDIO的配置界面,MX软件建议不设分频,但这里需要慎重,SDIOCLK的分频要按照自己硬件板子的情况设置,我用的某型号开发板,如果用最高频率,会出现TF卡读写不稳定,设置一下分频才好。

使用特权

评论回复
地板
wangjiahao88|  楼主 | 2018-9-19 10:27 | 只看该作者
设置完毕,生成代码和工程。打开工程,在usbd_storage_if.c文件里配置TF卡(SD卡)的基本IO操作。

在文件开头加入

#define BLOCK_SIZE                       512

使用特权

评论回复
5
wangjiahao88|  楼主 | 2018-9-19 10:27 | 只看该作者
extern SD_HandleTypeDef hsd;
extern HAL_SD_CardInfoTypedef SDCardInfo;

使用特权

评论回复
6
wangjiahao88|  楼主 | 2018-9-19 10:28 | 只看该作者
注意!上面这三行就算写到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 */
}

使用特权

评论回复
7
wangjiahao88|  楼主 | 2018-9-19 10:28 | 只看该作者
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 */
}

使用特权

评论回复
8
wangjiahao88|  楼主 | 2018-9-19 10:29 | 只看该作者
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 */
}

使用特权

评论回复
9
wangjiahao88|  楼主 | 2018-9-19 10:31 | 只看该作者
还有一个需要注意的,就是生成的代码中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;

}

使用特权

评论回复
10
wangjiahao88|  楼主 | 2018-9-19 10:31 | 只看该作者
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;

使用特权

评论回复
11
wangjiahao88|  楼主 | 2018-9-19 10:32 | 只看该作者
这句话生成出来的时候是disable的(然而在MX的图形界面中并没有发现怎么配置这段话),要人工改成enable,否则读写会不稳定。另,每一次MX重新生成,这里的enable又会被自动的改回去,老坑爹了。
到此,所有配置完成。

最后说下MX的另一个bug,就是使用FreeRTOS的时候HAL_Delay函数无法使用,最后发现原因是 stm32f1xx_it.c 文件中的SysTick_Handler
只加入了osSystickHandler()没加入HAL_IncTick(),把后者加入就好了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

462

主题

7477

帖子

29

粉丝