下载源码请关注公众号
之前的文章中介绍过STM32读写SD卡和FatFS文件系统相关的知识。今天将在这基础上介绍STM32通过USB口虚拟U盘的知识。即插入USB接口后,电脑将SD卡识别为U盘,可以直接读写SD卡内的文件。
硬件环境:STM32F407ZGT6
软件环境:STM32CubeMX v5.5.0
HAL库版本:STM32CubeF4 Firmware Package V1.24.0
1.STM32CubeMX配置
首先SD卡为SDIO接口,时钟等基础配置、SDIO接口配置和FatFs文件系统的配置参考之前的文章《STM32CubeMX之SDIO+FatFS读写SD卡》。之后需要配置USB接口,F407有两个USB接口,这里使用USB_OTG_FS接口,模式选择为设备模式Device_Only,其它配置默认即可。
在中间件菜单下选择USB_DEVICE,选择大容量存储设备(Mass Storage Class),其它参数默认即可。
生成代码之前,系统堆栈配置大一些:
2.程序编写
SD卡和文件系统读写文件等操作,参考之前文章,也不在这里介绍。
需要用户实现的只有USB虚拟U盘相关的函数,都在usbd_storage_if.c文件中。需要实现以下几个函数,其中中文注释的四个为必须实现的,其它的可选。
USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
STORAGE_Init_FS,
STORAGE_GetCapacity_FS, //获取U盘容量
STORAGE_IsReady_FS, //判断U盘状态
STORAGE_IsWriteProtected_FS,
STORAGE_Read_FS, //读U盘数据
STORAGE_Write_FS, //写U盘数据
STORAGE_GetMaxLun_FS,
(int8_t *)STORAGE_Inquirydata_FS
};
因为SD卡扇区读写等相关的驱动函数系统已经自动生成,这里只需要调用相关函数即可。四个函数的实现如下:
获取容量函数:
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
/* USER CODE BEGIN 3 */
*block_num = hsd.SdCard.BlockNbr;
*block_size = hsd.SdCard.BlockSize;
return (USBD_OK);
/* USER CODE END 3 */
}
判断U盘状态函数:
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
/* USER CODE BEGIN 4 */
uint8_t state = 0;
state = HAL_SD_GetState(&hsd) ;
if(HAL_SD_STATE_READY != state)
{
return USBD_FAIL ;
}
return (USBD_OK);
/* USER CODE END 4 */
}
U盘读数据函数:
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 6 */
if(HAL_OK != HAL_SD_ReadBlocks(&hsd,(uint8_t *)buf, blk_addr , blk_len, 1000))
{
return USBD_FAIL ;
}
return (USBD_OK);
/* USER CODE END 6 */
}
U盘写数据函数:
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 7 */
if(HAL_OK != HAL_SD_WriteBlocks(&hsd, (uint8_t *)buf, blk_addr , blk_len, 1000))
{
return USBD_FAIL ;
}
return (USBD_OK);
/* USER CODE END 7 */
}
完成之后,在主函数中初始化后添加相关测试程序,在SD卡新建一个文件,并写入数据。
retSD = f_mount(&SDFatFS, (TCHAR const*)SDPath, 0);//挂载
retSD = f_open(&SDFile,(const char*)"测试.txt",FA_CREATE_ALWAYS|FA_WRITE);
retSD = f_write(&SDFile,FileBuf,17,&bw);
retSD = f_close(&SDFile);
运行程序后,将USB线插入电脑,电脑识别出一个U盘,打开后可看到U盘内的文件及内容与所以写程序一致,说明程序正确。
通过电脑在U盘中新建一个文件,123.txt,任意写入一些内容。同时将刚才的写文件的程序改为读文件,并重新运行程序。
retSD = f_open(&SDFile,(const char*)"123.txt",FA_OPEN_EXISTING|FA_READ);//打开文件
if(retSD==FR_OK)
{
retSD = f_read(&SDFile,FileBuf,17,&bw);
}
retSD = f_close(&SDFile);
可以看到程序读取的数据与电脑上新建并写入的内容一致,说明程序正确。
3.总结
USB虚拟U盘的接口有很多应用,比如,可以通过USB接口直接SD卡内的导出文件。也可以利用该功能实现IAP功能,将bin文件拷贝到SD卡,Boot程序读取SD卡进行程序升级。应用时需要注意USB接口操作SD卡和程序操作SD卡不能同时进行,以免发生冲突。
欢迎关注公众号"嵌入式技术开发",大家可以后台给我留言沟通交流。如果觉得该公众号对你有所帮助,也欢迎推荐分享给其他人。