如何制作一个读取U盘文件系统的工程
来源:互联网 发布:淘宝详细图片尺寸 编辑:程序博客网 时间:2024/05/16 23:54
1 前言
本文介绍基于CubeMx如何创建一个读取U盘的工程,并通过FAT32文件系统创建和读取文件。
2 创建工程
读取U盘的程序在实际项目中经常会用到,这里我们基于STM3240G-EVAL评估板来示例如何创建一个读取U盘的程序。
在这个示例中,我们将通过一个按键来触发文件的读写。
2.1 硬件介绍
在正式创建工程之前,我们首先非常必要了解STM3240G-EVAL评估板相关的电路设计。
STM3240G-EVAL使用25M外部HSE,USB相关电路如下:
如上图所示,MCU通过PH5管脚来控制外部U盘的VBUS,低电平为使能。
按键相关电路如下:
2.2 创建CubeMx工程
STM3240G-EVAL评估板使用的是STM32F407IGH6,因此创建对应的CubeMx工程,在pingout页面中使能USB_OTG_FS外设,并设置为Host_Only:
并见PH5设置为GPIO_Output模式,用作使能VBUS。同时将PH15设置为外部中断,检测下降沿。
时钟树方面外部25M HSE,主频设置为168M,USB时钟48M,如下所示:
在配置方面,HAL层GPIO基本没有什么特殊,记得外部中断使用检测下降沿,这个是使用在按键中:
在NVIC中,一定要将USB的中断优先级高于按键中断,否则U盘不能正常读取。这里USB中断优先级设置为1,而外部中断15设置为5,如下图所示:
同时为USB选上MSC类,且勾上使用USB disk FAT文件系统:
中间件配置方面,其实可以使用默认,不过我们还是修改部分参数。
在文件系统配置方面:
我们只是简单地将其配置成支持中文,并支持长文件名。
最后,将栈和堆的空间大小都设置为2K:
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_LFN static char lfn[_MAX_LFN + 1]; /* Buffer to store the LFN */ fno.lfname = lfn; fno.lfsize = sizeof lfn;#endif res = 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_LFN fn = *fno.lfname ? fno.lfname : fno.fname;#else fn = fno.fname;#endif strcpy(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 结论
按键的中断EXIT15的优先级一定不能过于USB的中断优先级,否则代码运行到操作文件的时候回卡死!
通过CubeMx工具将一个比较复杂的读取文件系统工程大大简化的。
示例代码:http://download.csdn.net/detail/flydream0/9717879
- 如何制作一个读取U盘文件系统的工程
- 如何使用CubeMx制作一个基于SD卡的文件系统工程
- 如何使用CubeMx制作一个基于SD卡的文件系统工程(2)
- 教程:如何制作一个多功能U盘
- 如何制作一个自动运行U盘
- 制作带busybox的U盘文件系统详细步骤
- 如何制作纯净的U盘启动盘
- 制作一个简单的文件系统
- 如何制作u盘启动盘
- 如何制作U盘启动盘
- 如何制作U盘启动
- 如何制作多系统的u盘启动盘
- C#如何读取U盘插入的时间
- 如何制作U盘系统盘以及U盘安装操作系统的方法
- 如何把BOOTLOADER,内核,文件系统,制作成一个文件
- 如何制作U盘WinPE操作系统
- 如何制作系统盘和系统U盘
- 如何利用U盘制作启动盘
- 使用maven的过程
- 如何在VSCode内编译运行C++?
- READING NOTE: Beyond Skip Connections: Top-Down Modulation for Object Detection
- 2016 CVPR 所有论文
- PAT A1082
- 如何制作一个读取U盘文件系统的工程
- process.stdin的end事件如何触发?---关于nodejs底层的标准输入与输出的坑
- 屏幕适配入门-了解基本概念-图片适配
- Java开发必会的Linux命令
- 在Android app中切换自定义的输入法
- react-webpack-gulp-eslint自动化结构搭建以及优化
- linux基本命令
- 【POJ 3253 Fence Repair】+ 优先队列
- 使用gulp实现文件更改自动刷新