实现文件系统控制U盘
- 使用Keil新建项目,自动跳转至【Manage Run-Time Environment】;
- 将USB版本选择为MDK-Pro;
- 选择【File System-CORE】,配置【File System-Driver-USB】为1;
- 选择【USB-CORE】,配置【USB-Host】为1,并选择【USB-Host-MSC】;
- 选择【CMSIS-CORE】、【CMSIS-RTOS2(API)-Keil RTX5】
- 选择【Device-Startup】
- 选择【CMSIS-Driver-USB Host(API)-High-Speed】
- 剩余部分按照提示选择即可。选择完成后点击OK,自动启动CubeMX。
- 如下界面,点击Yes。进入Cube MX配置
- 选择【Connectivity-USB_OTG_FS】,【Mode】选择【Host_Only】,SOF、VBUS可不选。【NVIC Setting】中Enable【USB On The Go FS global interrupt】。其他默认不变,配置如下图:
- 选择【System Core-NVIC-Code generation】取消【USB On The Go FS global interrupt】的【Generate IRQ handler】,如下图:
- 修改时基源:选择【System Core-SYS】下【Timebase Source】,修改为非冲突定时器如TIM6
- 配置时钟:点击【System Core-RCC】,【High Speed Clock(HSE)】选择Crystal/Ceramic Resonator。切换到【Clock Configuration】配置时钟树,弹出自动配置提醒如下图:
- 选择No。时钟树配置如下图,其余时钟警告取允许的最大值即可。
- 点击【GENERATE CODE】生成代码。弹出如下窗口,手动关闭即可。关闭CubeMX。
- 回到Keil,弹出如下图提示,点击是,导入修改。
- 配置文件系统:打开【Project】栏选择【File System】——【FS_Config.c】,配置FS_INITIAL_CDRIVE值为7
- 进入【Options for Target】选择AC5编译器(使用AC6编译可能会出现报错、使用AC5编译可能会出现新组件版本无法识别的现象,可选择旧版本组件),此时编译会出现如下报错:
- 进stm32f7xx_it.c,删除重复定义的三个函数即可编译成功。
- main函数实现:
/* 包含两个头文件 */ #include "rl_usb.h" #include "rl_fs.h" /* main函数中必须调用以下四个函数 */ osKernelInitialize(); //操作系统内核初始化 USBH_Initialize(0); //USB-Host初始化(不初始化USB-Host会导致无法识别U盘) finit("U0:"); //初始化文件系统(不初始化文件系统可能导致文件系统调试界面告警) osKernelStart(); //启动操作系统内核
- 调试测试:下载程序进入debug,依次点击【VIEW】——【Watch Windows】,选择【RTX RTOS】、【File System】、【USB Device and Host】。如下图:
- 运行程序,三个组件正常运行:
- USB应用代码实现:工程中创建USB文件夹,在该文件夹右键点击【Add New Item to Group 'USB'】,根据引导创建模板例程。
- 在主线程中实现以下代码
#include "USBH_MSC.h"//该头文件在步骤24中创建,需手动在【Options for Target】中添加包含 void usb_task()//该线程需手动创建 { int32_t media_status, media_status_previous = USBH_MSC_ERROR_DRIVE; while(1) { media_status = USBH_MSC_DriveGetMediaStatus ("U0:"); if ((media_status == USBH_MSC_OK) && (media_status_previous != USBH_MSC_OK)) { switch (USBH_MSC_DriveMount (drive_name)) { case USBH_MSC_OK: fopen (...); break; case USBH_MSC_ERROR_FORMAT: fformat (drive_name, "/FAT32"); fopen (...); break; case USBH_MSC_ERROR: // Mount error break; } } media_status_previous = media_status; osThreadYield(); } }