esp32|ESP32-S2应用开发——USB通信(虚拟串口)

ESP32S2应用开发——USB通信(虚拟串口)
目录

  • ESP32S2应用开发——USB通信(虚拟串口)
    • 前言
    • 1 硬件介绍
      • 1.1 硬件连接
    • 2 软件开发
      • 2.1 安装开发板
      • 2.2 安装库
      • 2.3 运行示例代码
      • 2.4 USB传输速度测试
    • 结束语

前言 【esp32|ESP32-S2应用开发——USB通信(虚拟串口)】ESP32-S2是继ESP32之后新出的一款的MCU,而USB接口是ESP32-S2的一大特色,虽然使用的只是USB1.1协议,但是相比于串口而言传输速度还是要快很多的。对于音频或者视频等数据的传输,使用usb明显是比串口有优势的。
因为前段时间项目需求,需要用到ESP32-S2的USB,于是就花了些时间研究了一下,发现网上关于ESP32-S2 USB的介绍很少而且大多资料都过时了,于是就有了这篇博客。
好了,废话不多说了,马上开始讲解。
1 硬件介绍 本文的硬件配置如下:
模块 型号 说明
ESP32-S2 ESP32-S2-WROVER 这是乐鑫的一款模组,内部主要是用乐鑫的ESP32-S2再加上一个4M FLASH和2M PSRAM组成,开发板用的是乐鑫的ESP32-S2-SAOLA
ESP32-S2的引脚很多我就不一一介绍了,这一讲主要用到的UART0和USB(GPIO19,GPIO20)。
1.1 硬件连接
我这里用的是开发板,硬件连接比较简单。
UART0通过USB转TTL芯片连接到PC端。
USB通过GPIO19和GPIO20直连PC端的USB接口。
2 软件开发 2.1 安装开发板
关于ESP32-S2 Arduino的环境搭建我之前出过教程了,这里就不多说了,不懂的同学可以先看下我之前的博客。
2.2 安装库
打开Arduino IDE,依次打开 工具 -> 管理库…
在搜索框输入需要安装的库名称,找到对应的库,点击安装即可。
本文需要使用的Arduino库如下:
Arduino库 版本 说明
ESP32TinyUSB 1.3.4 USB相关库,使用该库要确保ESP32库版本在2.0.0以上
esp32 2.0.1 建议使用该版本,v2.0.2有个usb相关的结构体定义改了,跟ESP32TinyUSB库不兼容。
如果非要用2.0.2以上版本就需要在ESP32TinyUSB和esp32两者之前选择一个把client_event_callback的定义改掉
esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

2.3 运行示例代码
ESP32TinyUSB库自带很多examples,我们打开一个cdc的示例代码先测试一下USB通讯。
示例代码如下:
/** * Simple CDC device connect with putty to use it * author: chegewara * Serial - used only for logging * Serial1 - can be used to control GPS or any other device, may be replaced with Serial */ #include "cdcusb.h" #if CFG_TUD_CDC CDCusb USBSerial; class MyUSBCallbacks : public CDCCallbacks { void onCodingChange(cdc_line_coding_t const* p_line_coding) { int bitrate = USBSerial.getBitrate(); Serial.printf("new bitrate: %d\n", bitrate); }bool onConnect(bool dtr, bool rts) { Serial.printf("connection state changed, dtr: %d, rts: %d\n", dtr, rts); return true; // allow to persist reset, when Arduino IDE is trying to enter bootloader mode }void onData() { int len = USBSerial.available(); Serial.printf("\nnew data, len %d\n", len); uint8_t buf[len] = {}; USBSerial.read(buf, len); Serial.write(buf, len); }void onWantedChar(char c) { Serial.printf("wanted char: %c\n", c); } }; void setup() { Serial.begin(115200); USBSerial.setCallbacks(new MyUSBCallbacks()); USBSerial.setWantedChar('x'); if (!USBSerial.begin()) Serial.println("Failed to start CDC USB stack"); }void loop() { while (Serial.available()) { int len = Serial.available(); char buf1[len]; Serial.read(buf1, len); int a = USBSerial.write((uint8_t*)buf1, len); } }#endif

esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

运行结果如下:
设备管理器能看到两个com口(一个是串口转换芯片,一个是ESP32-S2的USB)。
esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

用串口助手先打开UART对应的端口,波特率115200。再打开一个串口助手,连接USB虚拟串口对应的com口,此时能看到UART会出现一些log。
esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

USB连接上之后,两个串口助手之间可以互发数据,说明USB通讯是没问题的。
esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

提示:如果烧录程序之后出现一直重启的现象,可能是因为MCU原本出厂的固件有一部分没有被擦除导致的,可以使用乐鑫的flash烧录工具对整个MCU进行擦除之后再烧录Arduino的程序。
2.4 USB传输速度测试
简单写一个测试代码用来测试USB数据传输的速度。
示例代码如下:
#include "cdcusb.h" #include "Arduino.h" #include #define FILE_SIZE 971240// 测试文件的大小 uint8_t *rx_buf; uint32_t rx_num = 0; uint8_t first_time_flag = 1; long lTime; CDCusb CDCUSBSerial; class MyCDCCallbacks : public CDCCallbacks { void onCodingChange(cdc_line_coding_t const* p_line_coding) { int bitrate = CDCUSBSerial.getBitrate(); Serial.printf("new bitrate: %d\n", bitrate); }bool onConnect(bool dtr, bool rts) { Serial.printf("connection state changed, dtr: %d, rts: %d\n", dtr, rts); return true; // allow to persist reset, when Arduino IDE is trying to enter bootloader mode }void onData() { if(first_time_flag) { first_time_flag = 0; lTime = micros(); }int len = CDCUSBSerial.available(); CDCUSBSerial.read(&rx_buf[rx_num], len); rx_num += len; if(rx_num >= FILE_SIZE) { lTime = micros() - lTime; Serial.printf("time: %f s \n", lTime / 1000000.0); Serial.printf("speed:%f kb/s", ((float)FILE_SIZE / 1024.0) / (lTime / 1000000.0)); first_time_flag = 1; rx_num = 0; } } }; void setup() { Serial.begin(115200); if (!CDCUSBSerial.begin()) Serial.println("Failed to start CDC USB stack"); CDCUSBSerial.setCallbacks(new MyCDCCallbacks()); rx_buf = (uint8_t*)ps_malloc(FILE_SIZE); }void loop() {}

通过串口助手往USB发送一个大文件(971240字节,约948.5kb)。
提示:这里串口助手打开文件时显示的时间是按当前波特率估算出来的,但是实际上我们用的是虚拟串口,USB传输是没有波特率这个参数的,这里波特率不管设置为多少,实际的速度都一样,都是以USB传输速度为准。
esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

通过ESP32-S2的串口0打印实际的传输的时间和速度。
esp32|ESP32-S2应用开发——USB通信(虚拟串口)
文章图片

经过sscom这个串口助手传输文件测试,ESP32-S2 USB的最大传输速度在190kb/s左右,实际上加上一些应用代码之后,速度会有所下降,约160kb/s左右(这个速度跟具体的应用有关)。
因为USB接收是中断处理的,MCU如果一直处于闲置状态,那USB的数据传输速度可以达到最大。反之,MCU如果一直在运行其他应用代码,那么在接收USB数据时只能通过频繁的中断来完成数据的读取,此时接收的效率明显是要下降一些的。另外,传输速度跟MCU的接收方式也有关系,USB1.1最大支持一次接收64字节,所以MCU在进入回调函数时,应该根据把当前收到的所有数据一次性读取完,而不是每次回调只读一个字节。
后期测试补充:
在使用sscom这个串口助手时,文件的传输速度跟设置的波特率无关,但是后来用另外一个串口助手(UartAssist)时发现用这个工具设置的波特率跟实际传输速度有关联,这就很奇怪了,因为这个只是虚拟串口,实际上是按照USB1.1协议来传输数据的,理论上不应该出现这种情况的。然后我测试了多种不同的波特率,发现波特率较小时,实际传输速度与波特率基本一致,波特率越大速度越快,当波特率增大到2M时,速度与之前sscom串口助手测试的速度接近。继续增大波特率到某个值之后,不管波特率设置多少,速度都不再增大了。最大传输速度在270kb/s左右。
从目前的现象来看,USB的传输速度跟串口工具本身也有关系,具体的原因还没搞清楚,有懂的老哥解答一下吗?
结束语 好了,关于ESP32-S2 USB的使用就介绍到这里。如果这篇文章对你有帮助,可以点赞收藏,如果还有什么问题,欢迎在评论区留言或者私信给我。
Arduino开发教程汇总:
https://blog.csdn.net/ShenZhen_zixian/article/details/121659482

    推荐阅读