1 前言

本文介绍基于CubeMx如何创建一个读取U盘的工程,并通过FAT32文件系统创建和读取文件。

2 创建工程

读取U盘的程序在实际项目中经常会用到,这里我们基于STM3240G-EVAL评估板来示例如何创建一个读取U盘的程序。

在这个示例中,我们将通过一个按键来触发文件的读写。

2.1 硬件介绍

在正式创建工程之前,我们首先非常必要了解STM3240G-EVAL评估板相关的电路设计。
STM3240G-EVAL使用25M外部HSE,USB相关电路如下:


图1 USB电路

如上图所示,MCU通过PH5管脚来控制外部U盘的VBUS,低电平为使能。
按键相关电路如下:


图2 按键相关电路

2.2 创建CubeMx工程

STM3240G-EVAL评估板使用的是STM32F407IGH6,因此创建对应的CubeMx工程,在pingout页面中使能USB_OTG_FS外设,并设置为Host_Only:


图3 USB_OTG_FS设置为主机模式

并见PH5设置为GPIO_Output模式,用作使能VBUS。同时将PH15设置为外部中断,检测下降沿。


图4 pinout分布

时钟树方面外部25M HSE,主频设置为168M,USB时钟48M,如下所示:


图5 时钟树设置

在配置方面,HAL层GPIO基本没有什么特殊,记得外部中断使用检测下降沿,这个是使用在按键中:


图6 按键检测外部中断

在NVIC中,一定要将USB的中断优先级高于按键中断,否则U盘不能正常读取。这里USB中断优先级设置为1,而外部中断15设置为5,如下图所示:


图7 中断优先级配置

同时为USB选上MSC类,且勾上使用USB disk FAT文件系统:


图8 USB MSC类和FAT文件系统

中间件配置方面,其实可以使用默认,不过我们还是修改部分参数。
在文件系统配置方面:


图9 文件系统参数配置

我们只是简单地将其配置成支持中文,并支持长文件名。
最后,将栈和堆的空间大小都设置为2K:


图10 堆栈大小设置

OK,接下来就可以生成工程了。

2.3 代码修改

在生成的代码中,首先我们对main函数进行修改,在main函数中我们需要做的工作主要有以下几件:

  • 完成系统初始化
  • 使能VBUS
  • 当检测到插入U盘时挂载文件系统
  • 当检测到U盘拔出时,卸载文件系统
    于是main函数如下所示:
int main(void)
{/* USER CODE BEGIN 1 */
static ApplicationTypeDef pre_state = APPLICATION_IDLE;FATFS fs;/* USER CODE END 1 *//* MCU Configuration----------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();MX_FATFS_Init();MX_USB_HOST_Init();/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOH, GPIO_PIN_5, GPIO_PIN_RESET);//enable usb VBUS/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */MX_USB_HOST_Process();/* USER CODE BEGIN 3 */if (pre_state != Appli_state){switch(Appli_state){case APPLICATION_DISCONNECT: //USB flash disk remove/* Register the file system object to the FatFs module */if(f_mount(NULL, "", 0) != FR_OK){USBH_UsrLog("ERROR : Cannot exit FatFs! \n");}break;case APPLICATION_READY:   //USB flash disk plugin/* Open or create a log file and ready to append */if(f_mount(&fs, "", 0) != FR_OK){break;}break;default:break;}}pre_state = Appli_state;}/* USER CODE END 3 */}

如上代码,程序通过拉低PH5管脚来使能VBUS。使用使用一个静态的局部变量pre_state来记录之前的U盘拔插状态,用以跟踪U盘的连接状态,当U盘插入时,立即挂载文件系统。当检测到U盘拔出时则卸载文件系统。

接下来看按键中断处理,这里,我们在按键中断中分别做3次测试,写文件测试,和文件扫描测试 :

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{static uint8_t step =0;if(USBH_MSC_IsReady(&hUsbHostFS)){switch(step ++){case 0:writefile_test(); //写文件测试break;case 1:readfile_test();    //读文件测试break;case 2:Explore_Disk("0:/", 1); //文件扫描测试break;default:break;}if(step >2){step =0;}}else{USBH_UsrLog("USB Device is not ready.\n");}
}

文件扫面测试,写问津测试,读文件测试:

FRESULT Explore_Disk(char *path, uint8_t recu_level)
{FRESULT res = FR_OK;FILINFO fno;DIR dir;char *fn;char tmp[14];uint8_t line_idx = 0;#if _USE_LFNstatic char lfn[_MAX_LFN + 1];   /* Buffer to store the LFN */fno.lfname = lfn;fno.lfsize = sizeof lfn;
#endifres = f_opendir(&dir, path);if(res == FR_OK){while(USBH_MSC_IsReady(&hUsbHostFS)){res = f_readdir(&dir, &fno);if(res != FR_OK || fno.fname[0] == 0){break;}if(fno.fname[0] == '.'){continue;}#if _USE_LFNfn = *fno.lfname ? fno.lfname : fno.fname;
#elsefn = fno.fname;
#endifstrcpy(tmp, fn);line_idx++;if(line_idx > 9){line_idx = 0;}if(recu_level == 1){USBH_UsrLog("   |__");}else if(recu_level == 2){USBH_UsrLog("   |   |__");}if((fno.fattrib & AM_MASK) == AM_DIR){strcat(tmp, "\n");USBH_UsrLog((void *)tmp);Explore_Disk(fn, 2);}else{strcat(tmp, "\n");USBH_UsrLog((void *)tmp);}if(((fno.fattrib & AM_MASK) == AM_DIR)&&(recu_level == 2)){Explore_Disk(fn, 2);}}f_closedir(&dir);}return res;
}
void writefile_test(void)
{FIL fil;FRESULT fr;/* Opens an existing file. If not exist, creates a new file. */fr = f_open(&fil, "0:/mytest.txt", FA_READ | FA_WRITE | FA_CREATE_ALWAYS);if (fr != FR_OK){return;}f_printf(&fil, "%s\n", "[USB]write txt OK!0123456789");/* Close the file */f_close(&fil);
}
void readfile_test(void)
{FIL fil;FRESULT fr;uint8_t buff[20];UINT off = 0;/* Opens an existing file. If not exist, creates a new file. */fr = f_open(&fil, "0:/mytest.txt", FA_READ);if (fr != FR_OK){return;}f_read(&fil, buff, 16, &off);buff[16] = 0;/* Close the file */f_close(&fil);
}

最后将U盘去下来插入到windows查看,可以正常考到测试文件mytest.txt文件,这证明结果是OK的。

3 结论

  1. 按键的中断EXIT15的优先级一定不能过于USB的中断优先级,否则代码运行到操作文件的时候回卡死!

  2. 通过CubeMx工具将一个比较复杂的读取文件系统工程大大简化的。

示例代码:http://download.csdn.net/detail/flydream0/9717879

如何制作一个读取U盘文件系统的工程相关推荐

  1. linux刻录win10u盘_如何用ultraiso制作一个系统U盘?WIN10系统U盘制作图文教程

    大家是不是偶尔会遇到电脑系统损坏的情况呢?你第一时间想到的是去找电脑店师傅来处理一下,但又是深夜了,怎么办?其实自己也可以解决的,前提是你有一个用于"救急"的U启动盘.今天就教你如 ...

  2. 制作一个启动U盘安装Ubuntu20.04

    制作一个启动U盘安装Ubuntu20.04 下载安装镜像制作工具UltralSO(软碟通) 下载 Ubuntu20.04 ISO 文件 制作启动盘 下载安装镜像制作工具UltralSO(软碟通) Ul ...

  3. 如何制作计算机启动盘,电脑该如何制作一个启动U盘

    为什么要制作启动U盘?相信各位小伙伴心里一定会有一个疑虑,现在小编先为大家解释一下,启动U盘是一个装有PE镜像文件的U盘,我们可以通过这个启动盘直接进入PE系统对电脑进行重装系统.而且这个启动盘可以随 ...

  4. 制作多系统U盘(一个U盘两个系统,适用于win)

    当一台电脑启动时,它会先启动主板上的BIOS系统,bios再从硬盘上读取MBR主引导记录,硬盘上的MBR运行后,就会启动Windows操作系统.GPT是另外一种更先进的磁盘系统分区方式,一种使用UEF ...

  5. 读取U盘 PID,VID,SN等信息

    这个也是从某位大师那里直接转来的....对我太有用了,,感激涕零!!! 因为工作需要,要写一个读取U盘PID,VID信息的程序,在网上找了很久都没有发现有相关的资料.相关的工作也搁置了很久,真是亏对公 ...

  6. deepin系统15.6版本安装执行那个exe文件_秒杀一众PE系统,制作强大的U盘启动系统,自制新一代装机神器

    安装电脑系统的方式有很多,是一个既复杂又简单的工作,有时候几分钟就可以装好,而有些时候却要折腾几个小时. 重装系统的时候有很大一部分原因就是因为系统损坏,无法正常进入系统才选择的重装,就拿以前安装原版 ...

  7. 联想笔记本启动u盘linux系统下载,制作linux启动u盘(rufus)

    制作linux系统和windows启动u盘,完全免费的自启动U盘系统制作工具,鲁弗斯是一种实用工具,帮助格式,并创建可引导的USB闪存驱动器,如USB钥匙/ pendrives,记忆棒等. 以下情况下 ...

  8. linux命令进u 盘,在Linux下制作一个磁盘文件,在u-boot 阶段对emmc 烧写整个Linux系统方法...

    在Linux 下制作一个磁盘文件, 可以给他分区,以及存储文件,然后dd 到SD卡便可启动系统. 在u-boot 下启动后可以读取该文件,直接在u-boot 阶段就可以做烧写操作,省略了进入系统后才进 ...

  9. Windows的启动u盘linux,如何在linux下制作一个windows的可启动u盘?

    如何在linux下制作一个windows的可启动u盘? 情景是这样的,有一个windows10的iso,现在想通过U盘安装,要求即支持UEFI(启动引导器),又支持Legacy(启动引导器),因为有一 ...

  10. 如何制作一个U盘启动盘和重装window系统

    一.如何制作一个U盘启动盘(以老毛桃为例) 前期准备 1.准备一个4G以上的U盘 2.备份U盘重要文件,制作过程中会格式化U盘. PS:因为此软件涉及对可移动磁盘的读写操作,部分杀毒软件和安全类软件会 ...

最新文章

  1. SQL Server 数据库基础编程
  2. 删除表格数据后自动刷新_表格中一键即可删除重复数据,你居然还用逐条排查?...
  3. HTML框架,链接,登录,注册联合应用
  4. 前端学习(1165):扩展运算符01
  5. java 根据类名示例化类_Java即时类| plusMillis()方法与示例
  6. 与虚拟现实技术相关联的计算机技术,虚拟现实技术与其他技术的关系是什么?-VR-形象思维VR...
  7. jumpserver(0.3.2版本)开源跳板机系统部署
  8. java并发编程基础-ReentrantLock及LinkedBlockingQueue源码分析
  9. java除法运算符号怎么打_Java实用教程:运算符
  10. 1 集群Linux环境搭建
  11. 信号量(semaphore)解决司机与售票员问题
  12. 禁止 input 自动填充
  13. idea在自动注入DiscoveryClient的时候报错
  14. Summaries and TensorBoard
  15. Oracle回收站机制
  16. BMS(电池管理系统)第五课 ——核心!!!SOH算法开发
  17. 打电话显示短信呼服务器,已启用短信呼服务 已启用短信呼服务是什么意思
  18. SpringBoot 配置文件加密的两种方式
  19. 模拟除法计算|L1-046 整除光棍 (20分)(思路)
  20. windows下tomcat集群配置(两种方法)

热门文章

  1. 基于anbox的云游戏技术简介
  2. 组装专用计算机系统吗,组装的电脑有自带系统吗?
  3. 医学知识-骨密度以及骨密度测量
  4. IDEA中如何进行XML解析
  5. 虚拟机安装后找不到操作系统
  6. IT程序员常去的论坛、社区、网站有哪些?
  7. json_encode转义中文问题
  8. oracle10g的系统视图(sys、system)
  9. sublime text2-text3 定义的不同浏览器的预览快捷键
  10. 近期币圈与美股的相关性