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 |
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的定义改掉 |
文章图片
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
文章图片
运行结果如下:
设备管理器能看到两个com口(一个是串口转换芯片,一个是ESP32-S2的USB)。
文章图片
用串口助手先打开UART对应的端口,波特率115200。再打开一个串口助手,连接USB虚拟串口对应的com口,此时能看到UART会出现一些log。
文章图片
USB连接上之后,两个串口助手之间可以互发数据,说明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-S2的串口0打印实际的传输的时间和速度。
文章图片
经过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
推荐阅读
- esp32|Arduino应用开发——spi flash(以esp32和w25qxx为例)
- esp32|ESP32烧录Arduino生成的bin文件
- HaaS解决方案|看屏幕眼睛干(没问题 用ESP32和 HaaS Python做一个 全自动加湿器)
- HaaS解决方案|开工大吉,ESP32 + HaaS Python为您送上久坐提醒器,好好工作更要注意健康哦
- HaaS解决方案|用ESP32打造一个物联网红外测温打卡机/春节结束急着上班(哒咩,再努力奋斗也要先测体温)
- HaaS解决方案|绿色节能,怎么用ESP32 + HaaS Python怎么做一个起夜小灯(接上个“智慧路灯”案例中的留下的地下室人体感应亮灭灯)
- 技术实践类|BMP280使用指南
- arduino|【毕业设计】基于arduino的蓝牙扫地机器人
- VS|ESP32 TTGO 1.14寸液晶屏使用 TFT_eSPI库驱动