OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 29|回复: 0

《ESP32-S3使用指南—IDF版 V1.6》第四十五章 Flash模拟U盘实验

[复制链接]

1177

主题

1189

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
5081
金钱
5081
注册时间
2019-5-8
在线时间
1268 小时
发表于 6 小时前 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2025-10-31 16:21 编辑

第四十五章 Flash模拟U盘实验

1)实验平台:正点原子DNESP32S3开发板

2)章节摘自【正点原子】ESP32-S3使用指南—IDF版 V1.6

3)购买链接:https://detail.tmall.com/item.htm?&id=768499342659

4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子DNESP32S3开发板技术交流群:132780729

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

本章我们介绍ESP32S3的USB HOST应用,即通过USB HOST功能,将某个分区表实现模拟U盘/读卡器等大容量USB存储设备。
本章分为如下几个小节:
45.1 Flash模拟U盘简介
45.2 硬件设计
45.3 程序设计
45.4 下载验证

45.1 Flash模拟U盘简介
所谓Flash模拟U盘,就类似于我们平常使用的U盘,我们只不过是将单片机与电脑通过USB数据线进行连接,从而进行数据传输。电脑能够识别出单片机通过外部Flash模拟出的U盘,在电脑上能够对该U盘进行文件的相互拷贝,并且重新上电后数据不丢失。通过对USB的了解,USB分设备(Device)模式和主机(Host)模式,使用单片机模拟U盘是让USB工作在设备(Device)模式下。
我们可以利用ESP32自带的USB功能,来实现一个Flash模拟U盘,从而通过USB,实现电脑与ESP32的数据互传。上位机无需编写专门的USB程序,只需要一个串口调试助手即可调试,非常实用。

45.2 硬件设计
45.2.1例程功能
本实验利用ESP32自带的USB功能,通过USB连接电脑后,子分区会在电脑上进行加载,并显示该子分区的容量,我们可测试子分区数据的读写了。
LED闪烁,提示程序运行,USB和电脑连接成功。
45.2.2硬件资源
1. LED灯
LED -IO0
2.独立按键
KEY0(XL9555) - IO1_7
KEY1(XL9555) - IO1_6
KEY2(XL9555) - IO1_5
KEY3(XL9555) - IO1_4
3. XL9555
IIC_SDA-IO41
IIC_SCL-IO42
4. SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳线帽将IO_SET和LCD_DC相连)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)
5. UART_NUM_0(U0TX、U0RX连接至板载USB转串口芯片上)
U0TXD-IO43
U0RXD-IO45
6. USB
45.2.3原理图
本章实验使用USB接口与PC进行连接,开发板板载了一个USB接口,用于连接其他USB设备,USB接口与MCU的连接原理图,如下图所示:
image001.png
45.2.3.1 USB接口与MCU的连接原理图
45.3 程序设计
45.3.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:
image004.png
图45.3.1.1Flash模拟U盘实验程序流程图
45.3.2 Flash模拟U函数解析
ESP-IDF提供了一套API来配置Flash。要使用此功能,需要导入必要的头文件:
  1. #include"ff.h"
  2. #include"diskio.h"
  3. #include"esp_vfs_fat.h"
  4. #include"tinyusb.h"
复制代码

接下来,作者将介绍一些常用的ESP32-S3中的Flash函数,这些函数的描述及其作用如下:
1挂载分区函数
该函数用给定的配置,来挂载分区,该函数原型如下所示:
  1. esp_err_tesp_vfs_fat_spiflash_mount_rw_wl(const char*base_path,
  2.                                            const char*partition_label,
  3.                                            constesp_vfs_fat_mount_config_t* mount_config,
  4.                                           wl_handle_t* wl_handle);
复制代码

该函数的形参描述如下表所示:
QQ截图20251031160758.png
表45.3.2.1esp_vfs_fat_spiflash_mount_rw_wl ()函数形参描述
该函数的返回值描述,如下表所示:
QQ截图20251031160812.png
表45.3.2.2函数esp_vfs_fat_spiflash_mount_rw_wl()返回值描述
该函数使用esp_vfs_fat_mount_config_t类型的结构体变量传入,该结构体的定义如下所示:
QQ截图20251031160824.png
表45.3.2.3esp_vfs_fat_mount_config_t结构体参数值描述
完成上述结构体参数配置之后,可以将结构传递给 esp_vfs_fat_spiflash_mount_rw_wl () 函数,用以挂载分区。
更多有关USB函数的介绍,请读者们回顾上一章节的内容。
45.3.3 Flash模拟U驱动解析
在IDF版的34_usb_flash_u例程中,作者在34_usb_flash_u\components路径下新增了Flash驱动文件。
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。
本实验,我们将相TinyUSB库文件拷贝到components文件夹下,在APP文件夹下的文件则是我们基于TinyUSB自行编写的代码。最终得到如图45.3.3.1所示的工程:
      image005.png
45.3.3.1 Flash模拟U工程分组
上图中位于components文件夹下的是我们自己编写的一些外设驱动,main文件夹下包含了一个APP文件与一个后缀为.yml的文件。APP文件夹下包含的是FLASH模拟U盘(USB)代码,而后缀为.yml的文件其主要作用是将项目中各组件的依赖项定义在单独的清单文件中,并以上图所示的方式进行命名。在我们的例程中提现出的作用就是简化了整个工程结构。我们在编译的过程中,系统便会帮我们自动生成USB外设所需要的依赖库:espressif_esp_tinyusb以及espressif_tinyusb。做到了即能简化项目工程,又能有效规避了在编译中遇到的错误,但前提是运行时得确保个人的电脑处于联网状态。
45.3.4 CMakeLists.txt文件
打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
  1. set(src_dirs
  2.             IIC
  3.             LCD
  4.             LED
  5.             SPI
  6.             XL9555)

  7. set(include_dirs
  8.             IIC
  9.             LCD
  10.             LED
  11.             SPI
  12.             XL9555)

  13. set(requires
  14.             driver)

  15. idf_component_register(SRC_DIRS${src_dirs}
  16. INCLUDE_DIRS ${include_dirs}REQUIRES ${requires})

  17. component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
复制代码

该路径下的CmakeList文件并没有新增内容,主要变化在于main文件。
打开本实验main文件下的CMakeLists.txt文件,其内容如下所示:
  1. idf_component_register(
  2.     SRC_DIRS
  3.         "."
  4.         "app"
  5.     INCLUDE_DIRS
  6.         "."
  7.         "app")
复制代码

上述的红色app驱动需要由开发者自行添加,以确保USB驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了USB驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。
45.3.5 实验应用代码
打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。
  1. i2c_obj_ti2c0_master;

  2. /**
  3. * @brief      程序入口
  4. * @param      无
  5. * @retval     无
  6. */
  7. voidapp_main(void)
  8. {
  9.     esp_err_t ret;

  10.     ret =nvs_flash_init();                             /* 初始化NVS */
  11.    
  12. if (ret ==ESP_ERR_NVS_NO_FREE_PAGES ||
  13.         ret ==ESP_ERR_NVS_NEW_VERSION_FOUND)
  14.     {
  15.         ESP_ERROR_CHECK(nvs_flash_erase());
  16.         ret =nvs_flash_init();
  17.     }

  18.     ESP_ERROR_CHECK(ret);

  19.     led_init();                                           /* 初始化LED */
  20.     i2c0_master =iic_init(I2C_NUM_0);                    /* 初始化IIC0 */
  21.     spi2_init();                                          /* 初始化SPI */
  22.     xl9555_init(i2c0_master);                               /* 初始化IO扩展芯片 */
  23.     lcd_init();                                           /* 初始化LCD */
  24.    
  25.     /* 显示实验信息 */
  26.     lcd_show_string(30, 50, 200, 16, 16, "ESP32-S3", RED);
  27.     lcd_show_string(30, 70, 200, 16, 16, "USBFLASH TEST", RED);
  28.     lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
  29.     lcd_show_string(30, 110, 200, 16, 16, "status:", RED);
  30.     tud_usb_flash();                                     /* USB初始化 */

  31.     while(1)
  32.     {
  33.         if ((g_usbdev.status& 0x0f) == 0x01)
  34.         {
  35.             lcd_show_string(110,
  36.                                110,
  37.                                lcd_self.width,
  38.                                16,
  39.                                16,
  40.                                "connectsuccess.....",
  41.                                BLUE);
  42.         }
  43.         else if ((g_usbdev.status& 0x0f) == 0x00)
  44.         {
  45.             lcd_show_string(110,
  46.                                110,
  47.                                lcd_self.width,
  48.                                16,
  49.                                16,
  50.                                "connectfail........",
  51.                                BLUE);
  52.         }

  53.         LED_TOGGLE();
  54.         vTaskDelay(500);
  55.     }
  56. }
复制代码

此部分代码比较简单,通过tud_usb_flash()等函数初始化USB。由于该实验例程需要系统将storage分区模拟成U盘,所以在该函数中需要初始化SPIFFS分区,其次是用USB设备安装函数,用以USB设备登记。同时,LCD显示实验信息,LED闪烁以示程序正在运行。

45.4下载验证
将程序下载到开发板后(注意:USB数据线,要插在USB端口!而不是UART端口!),我们打开设备管理器(我用的是WIN10),在端口(COM和LPT)里面可以发现多出了一个COM25的设备,这就是USB虚拟的串口设备端口,如下图所示:
      image007.png
45.4.1 通过设备管理器查看USB虚拟的串口设备端口
如图45.4.1,ESP32通过Flash模拟U盘,被电脑识别了,通用串行总线控制器显示的是:USB大容量存储设备(其实也不算大,也就差不多4MB...)。此时,开发板的LED在闪烁,提示程序运行。开发板的LCD显示“connect success.....”,如下图所示:
image009.png
45.4.2 USB虚拟串口连接成功
然后我们打开“我的电脑”,可以看见界面显示了通过Flash模拟U盘后的容量大小,如下图所示:
      image011.png
45.4.3 ESP32 Flash模拟U盘测试
至此,Flash模拟U盘实验就完成了,通过本实验,我们就可以利用ESP32的Flash进行U盘模拟。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-10-31 23:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表