第四十四章 USB虚拟串口(Slave)实验
本章,我们将向大家介绍如何利用USB在开发板实现一个USB虚拟串口,通过USB与电脑数据数据交互。 本章分为如下几个小节: 44.1 USB虚拟串口简介 44.2 硬件设计 44.3 程序设计 44.4 下载验证
44.1 USB虚拟串口简介 USB虚拟串口,简称VCP,是Virtual COM Port的简写,它是利用USB的CDC类来实现的一种通信接口。CDC(Communication Device Class)类是 USB2.0 标准下的一个设备类,定义了通信相关设备的抽象集合。 我们可以利用ESP32自带的USB功能,来实现一个USB虚拟串口,从而通过USB,实现电脑与ESP32的数据互传。上位机无需编写专门的USB程序,只需要一个串口调试助手即可调试,非常实用。 44.2 硬件设计 44.2.1 例程功能 本实验利用ESP32自带的USB功能,连接电脑USB,虚拟出一个USB串口,实现电脑和开发板的数据通信。本例程功能完全同实验4(串口通信实验),只不过串口变成了ESP32的USB虚拟串口。当USB连接电脑(USB线插入USB_SLAVE接口),开发板将通过USB和电脑建立连接,并虚拟出一个串口。 LED闪烁,提示程序运行。USB和电脑连接成功后。 44.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-IO44 6. USB 44.2.3 原理图 本章实验使用USB接口与PC进行连接,开发板板载了一个USB接口,用于连接其他USB设备,USB接口与MCU的连接原理图,如下图所示: 图44.2.3.1 USB接口与MCU的连接原理图 44.3 程序设计 44.3.1 程序流程图 程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图: 图44.3.1.1 USB虚拟串口实验程序流程图 44.3.2 USB虚拟串口函数解析 ESP-IDF提供了一套API来配置USB。要使用此功能,需要导入必要的头文件: #include "tinyusb.h" #include "tusb_cdc_acm.h" 接下来,作者将介绍一些常用的ESP32-S3中的USB函数,这些函数的描述及其作用如下: 1,USB设备登记 该函数用给定的配置,来配置USB设备,该函数原型如下所示: esp_err_t tinyusb_driver_install(const tinyusb_config_t *config); 该函数的形参描述如下表所示: 表44.3.2.1 tinyusb_driver_install ()函数形参描述 该函数的返回值描述,如下表所示: 表44.3.2.2 函数tinyusb_driver_install ()返回值描述 该函数使用tinyusb_config_t类型的结构体变量传入,该结构体的定义如下所示: 表44.3.2.3 i2s_pin_config_t结构体参数值描述 2,USB设备初始化 该函数用给定的配置,来初始化USB设备,该函数原型如下所示: esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg); 该函数的形参描述如下表所示: 表44.3.2.4 tusb_cdc_acm_init ()函数形参描述 该函数的返回值描述,如下表所示: 表44.3.2.5 函数tusb_cdc_acm_init ()返回值描述 该函数使用tinyusb_config_cdcacm_t类型的结构体变量传入,该结构体的定义如下所示: | | | | | | | | | | | | | 指向' tusb_cdcacm_callback_t '类型的函数的指针,该函数将作为回调处理,例程中配置为NULL | callback_line_state_changed | | callback_line_coding_changed | |
表44.3.2.6 tinyusb_config_cdcacm_t结构体参数值描述 3,注册回调函数 该步骤用以注册回调函数,该函数原型如下所示: esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type); 该函数的形参描述如下表所示: 表44.3.2.7 tinyusb_cdcacm_register_callback ()函数形参描述 该函数的返回值描述,如下表所示: 表44.3.2.8 函数tinyusb_cdcacm_register_callback ()返回值描述 4,发送数据1 该函数将数据从字节数组写入写入缓冲区,该函数原型如下所示: size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size); 该函数的形参描述如下表所示: 表44.3.2.9 tinyusb_cdcacm_write_queue ()函数形参描述 该函数的返回值描述,如下表所示: 表44.3.2.10 函数tinyusb_cdcacm_write_queue ()返回值描述 5,发送数据2 该函数从写缓冲区发送所有数据,该函数原型如下所示: esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks); 该函数的形参描述如下表所示: 表44.3.2.11 tinyusb_cdcacm_write_flush ()函数形参描述 该函数的返回值描述,如下表所示: 表44.3.2.12 函数tinyusb_cdcacm_write_flush ()返回值描述 44.3.3 USB虚拟串口驱动解析 在IDF版的33_usb_uart例程中,作者在33_usb_uart \components路径下新增了USB驱动文件。 这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。 本实验,我们将相TinyUSB库文件拷贝到components文件夹下,在APP文件夹下的文件则是我们基于TinyUSB自行编写的代码。最终得到如下图所示的工程: 图44.3.3.1 USB虚拟串口工程分组 上图中位于components文件夹下的是我们自己编写的一些外设驱动,main文件夹下包含了一个APP文件与一个后缀为.yml的文件。APP文件夹下包含的是USB模拟串口代码,而后缀为.yml的文件其主要作用是将项目中各组件的依赖项定义在单独的清单文件中,并以上图所示的方式进行命名。在我们的例程中提现出的作用就是简化了整个工程结构。我们在编译的过程中,系统便会帮我们自动生成USB外设所需要的依赖库:espressif_esp_tinyusb以及espressif_tinyusb。做到了即能简化项目工程,又能有效规避了在编译中遇到的错误,但前提是运行时得确保个人的电脑处于联网状态。 44.3.4 CMakeLists.txt文件 打开本实验BSP下的CMakeLists.txt文件,其内容如下所示: set(src_dirs IIC LCD LED SPI XL9555) set(include_dirs IIC LCD LED SPI XL9555) set(requires driver) idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires}) component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format) 该路径下的CmakeList文件并没有新增内容,主要变化在于main文件。 打开本实验main文件下的CMakeLists.txt文件,其内容如下所示: idf_component_register( SRC_DIRS "." "app" INCLUDE_DIRS "." "app") 上述的红色app驱动需要由开发者自行添加,以确保USB驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了USB驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。 44.3.5 实验应用代码 打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。 i2c_obj_t i2c0_master; /** * @param 无 * @retval 无 */ void app_main(void) { esp_err_t ret; ret = nvs_flash_init(); /* 初始化NVS */ if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); led_init(); /* 初始化LED */ i2c0_master = iic_init(I2C_NUM_0); /* 初始化IIC0 */ spi2_init(); /* 初始化SPI */ xl9555_init(i2c0_master); /* 初始化IO扩展芯片 */ lcd_init(); /* 初始化LCD */ /* 显示实验信息 */ lcd_show_string(30, 50, 200, 16, 16, "ESP32-S3", RED); lcd_show_string(30, 70, 200, 16, 16, "USB USART TEST", RED); lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED); tud_usb_usart(); /* USB初始化 */ while(1) { LED_TOGGLE(); vTaskDelay(500); } } 此部分代码比较简单,通过tud_usb_usart()等函数初始化USB,在该函数中需要注册一个调用CDC事件的回调函数。此时,如果回调已经注册,那么它将会被覆盖。同时,LCD显示实验信息,LED闪烁以示程序正在运行。 44.4 下载验证 本例程的测试,不需要安装特定的USB驱动,开发者只需用数据线将USB接口(不是UART接口) 与PC端连接起来即可,并打开串口助手,选择对应的端口号进行数据发送操作。我们打开设备管理器(我用的是WIN10),在端口(COM和LPT)里面可以发现多出了一个COM8的设备,这就是USB虚拟的串口设备端口,如图44.3.1所示: 图44.4.1 通过设备管理器查看USB虚拟的串口设备端口 如图44.4.1,ESP32通过USB虚拟的串口,被电脑识别了,端口号为:COM8(可变),字符串名字为:USB串行设备(COM8)。此时,开发板的LED闪烁,提示程序运行,如图44.4.2所示: 图44.4.2 USB虚拟串口连接成功 然后我们打开XCOM,选择COM8(需根据自己的电脑识别到的串口号选择),并打开串口(注意:波特率可以随意设置),就可以进行测试了,如图44.4.3所示: 图44.4.3 ESP32虚拟串口通信测试 可以看到,我们的串口调试助手,按发送按钮,可以收到电脑发送给ESP32的数据(原样返回),说明我们的实验是成功的。 至此,USB虚拟串口实验就完成了,通过本实验,我们就可以利用ESP32的USB,直接和电脑进行数据互传了,具有广泛的应用前景。
|