你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
aimejia 发布时间:2018-5-29 10:25
本帖最后由 aimejia 于 2018-5-29 10:27 编辑

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

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

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

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

1.png

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

2.png

图2 按键相关电路
2.2 创建CubeMx工程
STM3240G-EVAL评估板使用的是STM32F407IGH6,因此创建对应的CubeMx工程,在pingout页面中使能USB_OTG_FS外设,并设置为Host_Only:
USB_OTG_FS设置为主机模式

3.png

图3 USB_OTG_FS设置为主机模式
并见PH5设置为GPIO_Output模式,用作使能VBUS。同时将PH15设置为外部中断,检测下降沿。
pinout分布

4.png

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

5.png

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

6.png

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

7.png

图7 中断优先级配置
同时为USB选上MSC类,且勾上使用USB disk FAT文件系统:
USB MSC类和FAT文件系统

8.png

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

9.png

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

10.png

图10 堆栈大小设置
OK,接下来就可以生成工程了。

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

完成系统初始化
使能VBUS
当检测到插入U盘时挂载文件系统
当检测到U盘拔出时,卸载文件系统
于是main函数如下所示:
  1. int main(void)
  2. {
  3.   /* USER CODE BEGIN 1 */
  4. static ApplicationTypeDef pre_state = APPLICATION_IDLE;
  5.    FATFS fs;
  6.   /* USER CODE END 1 */
  7.   /* MCU Configuration----------------------------------------------------------*/
  8.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  9.   HAL_Init();
  10.   /* Configure the system clock */
  11.   SystemClock_Config();
  12.   /* Initialize all configured peripherals */
  13.   MX_GPIO_Init();
  14.   MX_FATFS_Init();
  15.   MX_USB_HOST_Init();
  16.   /* USER CODE BEGIN 2 */
  17. HAL_GPIO_WritePin(GPIOH, GPIO_PIN_5, GPIO_PIN_RESET);//enable usb VBUS
  18.   /* USER CODE END 2 */
  19.   /* Infinite loop */
  20. /* USER CODE BEGIN WHILE */
  21.   while (1)
  22.   {
  23.   /* USER CODE END WHILE */
  24.     MX_USB_HOST_Process();
  25.   /* USER CODE BEGIN 3 */
  26.     if (pre_state != Appli_state)
  27.     {
  28.         switch(Appli_state)
  29.         {
  30.             case APPLICATION_DISCONNECT: //USB flash disk remove
  31.                 /* Register the file system object to the FatFs module */
  32.                 if(f_mount(NULL, "", 0) != FR_OK)
  33.                 {
  34.                     USBH_UsrLog("ERROR : Cannot exit FatFs! \n");
  35.                 }
  36.                 break;
  37.             case APPLICATION_READY:   //USB flash disk plugin
  38.                 /* Open or create a log file and ready to append */
  39.                 if(f_mount(&fs, "", 0) != FR_OK)
  40.                 {
  41.                     break;
  42.                 }
  43.                 break;
  44.             default:
  45.                 break;
  46.             }
  47.         }
  48.         pre_state = Appli_state;
  49.   }
  50.   /* USER CODE END 3 */
  51. }
复制代码
如上代码,程序通过拉低PH5管脚来使能VBUS。使用使用一个静态的局部变量pre_state来记录之前的U盘拔插状态,用以跟踪U盘的连接状态,当U盘插入时,立即挂载文件系统。当检测到U盘拔出时则卸载文件系统。

接下来看按键中断处理,这里,我们在按键中断中分别做3次测试,写文件测试,和文件扫描测试 :
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  2. {
  3.     static uint8_t step =0;
  4.     if(USBH_MSC_IsReady(&hUsbHostFS))
  5.     {
  6.         switch(step ++)
  7.         {
  8.         case 0:
  9.             writefile_test(); //写文件测试
  10.             break;
  11.         case 1:
  12.             readfile_test();    //读文件测试
  13.             break;
  14.         case 2:
  15.             Explore_Disk("0:/", 1); //文件扫描测试
  16.             break;
  17.         default:
  18.             break;
  19.         }
  20.         if(step >2)
  21.         {
  22.             step =0;
  23.         }
  24.     }
  25.     else
  26.     {
  27.         USBH_UsrLog("USB Device is not ready.\n");
  28.     }
  29. }
复制代码
文件扫面测试,写问津测试,读文件测试:
  1. FRESULT Explore_Disk(char *path, uint8_t recu_level)
  2. {
  3.   FRESULT res = FR_OK;
  4.   FILINFO fno;
  5.   DIR dir;
  6.   char *fn;
  7.   char tmp[14];
  8.   uint8_t line_idx = 0;

  9. #if _USE_LFN
  10.   static char lfn[_MAX_LFN + 1];   /* Buffer to store the LFN */
  11.   fno.lfname = lfn;
  12.   fno.lfsize = sizeof lfn;
  13. #endif

  14.   res = f_opendir(&dir, path);
  15.   if(res == FR_OK)
  16.   {
  17.     while(USBH_MSC_IsReady(&hUsbHostFS))
  18.     {
  19.       res = f_readdir(&dir, &fno);
  20.       if(res != FR_OK || fno.fname[0] == 0)
  21.       {
  22.         break;
  23.       }
  24.       if(fno.fname[0] == '.')
  25.       {
  26.         continue;
  27.       }

  28. #if _USE_LFN
  29.       fn = *fno.lfname ? fno.lfname : fno.fname;
  30. #else
  31.       fn = fno.fname;
  32. #endif
  33.       strcpy(tmp, fn);

  34.       line_idx++;
  35.       if(line_idx > 9)
  36.       {
  37.         line_idx = 0;
  38.       }

  39.       if(recu_level == 1)
  40.       {
  41.         USBH_UsrLog("   |__");
  42.       }
  43.       else if(recu_level == 2)
  44.       {
  45.         USBH_UsrLog("   |   |__");
  46.       }
  47.       if((fno.fattrib & AM_MASK) == AM_DIR)
  48.       {
  49.         strcat(tmp, "\n");
  50.         USBH_UsrLog((void *)tmp);
  51.         Explore_Disk(fn, 2);
  52.       }
  53.       else
  54.       {
  55.         strcat(tmp, "\n");
  56.         USBH_UsrLog((void *)tmp);
  57.       }

  58.       if(((fno.fattrib & AM_MASK) == AM_DIR)&&(recu_level == 2))
  59.       {
  60.         Explore_Disk(fn, 2);
  61.       }
  62.     }
  63.     f_closedir(&dir);
  64.   }
  65.   return res;
  66. }
  67. void writefile_test(void)
  68. {
  69.     FIL fil;
  70.     FRESULT fr;

  71.     /* Opens an existing file. If not exist, creates a new file. */
  72.     fr = f_open(&fil, "0:/mytest.txt", FA_READ | FA_WRITE | FA_CREATE_ALWAYS);
  73.     if (fr != FR_OK)
  74.     {
  75.         return;
  76.     }
  77.     f_printf(&fil, "%s\n", "[USB]write txt OK!0123456789");

  78.     /* Close the file */
  79.     f_close(&fil);
  80. }
  81. void readfile_test(void)
  82. {
  83.     FIL fil;
  84.     FRESULT fr;
  85.     uint8_t buff[20];
  86.     UINT off = 0;

  87.     /* Opens an existing file. If not exist, creates a new file. */
  88.     fr = f_open(&fil, "0:/mytest.txt", FA_READ);
  89.     if (fr != FR_OK)
  90.     {
  91.         return;
  92.     }

  93.     f_read(&fil, buff, 16, &off);
  94.     buff[16] = 0;

  95.     /* Close the file */
  96.     f_close(&fil);
  97. }
复制代码

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

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

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



转载自flydream0


收藏 2 评论0 发布时间:2018-5-29 10:25

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版