Arduino ESP32 USB CDC功能使用介绍
- 📌有关USB CDC原文档介绍:
https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/usb_cdc.html
- 📍有关ESP32-S/C 系列 USB 外设介绍详情页:
https://espressif-docs.readthedocs-hosted.com/projects/espressif-esp-iot-solution/zh-cn/latest/usb/usb_overview.html
- ✨在Arduino IDE开发环境下,ESP32 USB CDC功能是通过Arduino IDE面板上的功能菜单,配置选项完成设置的。例如:
-
🌿在Arduino IDE环境下,如果只是想让USB CDC作为调试串口使用,那么仅需要使能
USB CDC On Boot
选项即可(该选项配置为Disabled
,则在代码中如果使用Serial.begin()
则选择的是配置的为硬件串口0。 -
✨同样在VSCode PIO环境下,指定输出方式,可以在
platformio.ini
文件中,添加相应的参数.例如:
build_flags =
; -DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1 ;编译会有警告提示:宏重复定义
- 在
platformio.ini
中添加编译参数,会有警告的原因,在于所选择的型号对应的配置文件:\.platformio\platforms\espressif32\boards
内的对应.json中已经定义了相关编译参数。可以直接在对应的开发板型号的.json
文件中修改保持,就不需要在platformio.ini
中定义。
C:\Users\Administrator\.platformio\platforms\espressif32\boards
"extra_flags": [
"-DARDUINO_ESP32_S3R8N16",
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_USB_CDC_ON_BOOT=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
]
在不配置上面参数情况下,在VSCode PIO环境下,有些ESP32开发板型号默认是USB CDC方式输出的。如果要指定到串口0上输出,那么将值设置为0。
- 例如:
4d_systems_esp32s3_gen4_r8n16
,具体开发板型号Serial
所指定的是哪个外设,可以在\.platformio\packages\framework-arduinoespressif32\cores\esp32\HardwareSerial.h
文件内,找到相关宏定义。
- 🔱USB CDC相关的API函数大部分属于Stream类,和Serial、WiFiClient使用方法类似。
🌼USB CDC 和硬件串口0数据相互转发测试例程
- 🏷测试对象:
ESP32s3
- 🔧Arduno IDE 选项配置:
USB CDC On Boot
必须使能,和USB Mode设置:USB-OTG
- 🔖在例程中同时使用了硬件串口0和USB CDC串口功能。
- ✨需要注意,本程序中,USB CDC接收数据的处理,是在相应的事件回调中处理,而不是在loop()循环中处理。
/* ESP32 USB CDC介绍文档:
https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/api/usb_cdc.html
*/
#ifndef ARDUINO_USB_MODE
#error This ESP32 SoC has no Native USB interface
#elif ARDUINO_USB_MODE == 1
#warning This sketch should be used when USB is in OTG mode
void setup() {}
void loop() {}
#else
#include "USB.h"
#if ARDUINO_USB_CDC_ON_BOOT
#define HWSerial Serial0
#define USBSerial Serial
#else
#define HWSerial Serial
USBCDC USBSerial;
#endif
static void usbEventCallback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == ARDUINO_USB_EVENTS) {
arduino_usb_event_data_t* data = (arduino_usb_event_data_t*)event_data;
switch (event_id) {
case ARDUINO_USB_STARTED_EVENT:
Serial.println("USB PLUGGED");
break;
case ARDUINO_USB_STOPPED_EVENT:
Serial.println("USB UNPLUGGED");
break;
case ARDUINO_USB_SUSPEND_EVENT:
Serial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_wakeup_en);
break;
case ARDUINO_USB_RESUME_EVENT:
Serial.println("USB RESUMED");
break;
default:
break;
}
} else if (event_base == ARDUINO_USB_CDC_EVENTS) {
arduino_usb_cdc_event_data_t* data = (arduino_usb_cdc_event_data_t*)event_data;
switch (event_id) {
case ARDUINO_USB_CDC_CONNECTED_EVENT:
Serial.println("CDC CONNECTED");
break;
case ARDUINO_USB_CDC_DISCONNECTED_EVENT:
Serial.println("CDC DISCONNECTED");
break;
case ARDUINO_USB_CDC_LINE_STATE_EVENT:
Serial.printf("CDC LINE STATE: dtr: %u, rts: %u\n", data->line_state.dtr, data->line_state.rts);
break;
case ARDUINO_USB_CDC_LINE_CODING_EVENT:
Serial.printf("CDC LINE CODING: bit_rate: %lu, data_bits: %u, stop_bits: %u, parity: %u\n", data->line_coding.bit_rate, data->line_coding.data_bits, data->line_coding.stop_bits, data->line_coding.parity);
break;
case ARDUINO_USB_CDC_RX_EVENT:
// Serial.printf("CDC RX [%u]:", data->rx.len);
// {
// uint8_t buf[data->rx.len];
// size_t len = USBSerial.read(buf, data->rx.len);
// Serial.write(buf, len);
// }
// Serial.println();
{
String USBData = USBSerial.readString(); // 将接收到的信息使用readString()存储于USBData变量
Serial0.print("Received USBCDC Data: "); // 然后通过硬件串口0监视器输出USBData变量内容
Serial0.println(USBData); // 以便查看USBData变量的信息
}
break;
case ARDUINO_USB_CDC_RX_OVERFLOW_EVENT:
Serial.printf("CDC RX Overflow of %d bytes", data->rx_overflow.dropped_bytes);
break;
default:
break;
}
}
}
void setup() {
Serial0.begin(115200); //硬件串口
Serial.setDebugOutput(true);
delay(3000);
//Serial.println("USB CDC communication");
USB.onEvent(usbEventCallback);
USBSerial.onEvent(usbEventCallback);
USBSerial.begin();//在USB CDC On Boot使能情况下,这里是USBCDC
USB.begin();
// USBSerial.println("USB CDC communication");
}
void loop() {
if (Serial0.available()) {
// size_t l = Serial.available();
// uint8_t b[l];
// l = Serial.read(b, l);
// USBSerial.write(b, l);
USBSerial.println("Serial Data Available..."); // 通过USBCDC串口监视器通知用户
String SerialData = Serial0.readString(); // 将接收到的信息使用readString()存储于serialData变量
USBSerial.print("Received Serial Data: "); // 然后通过USBCDC串口监视器输出serialData变量内容
USBSerial.println(SerialData); // 以便查看serialData变量的信息
}
/*
// if(USBSerial.available()){
if(Serial.available()){
// Serial0.println("USBCDC Data Available..."); // 通过串口监视器通知用户
String USBData = USBSerial.readString(); // 将接收到的信息使用readString()存储于serialData变量
Serial0.print("Received USBCDC Data: "); // 然后通过串口监视器输出serialData变量内容
Serial0.println(USBData); // 以便查看serialData变量的信息
}
*/
}
#endif /* ARDUINO_USB_MODE */
-
📜通讯效果:
-
📘USB CDC 仅作为调试输出使用例程
- 🔖测试对象:ESP32S3
- 🔧配置选项:
/*
Blink
Arduino IDE
*/
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin();//在USB CDC On Boot使能(Enabled)情况下,这里是USBCDC
// Serial.begin(115200); // 在USB CDC On Boot没有使能(Disabled)情况下,启动的是硬件串口0通信,波特率为115200
Serial.setDebugOutput(true);
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
Serial.println("USB CDC Data");
}
- 🔖串口信息打印:
📙PlatformIO 环境下串口和USBCDC选择方式
- 🌿所测试的开发板型号:
4d_systems_esp32s3_gen4_r8n16
Serial
默认是作为USBCDC使用,Serial1
为串口1(Rx:15,Tx:16),Serial2
为串口1(Rx:19,Tx:20),
#include <Arduino.h>
// #include "USB.h"
#define LED_BUILTIN 38
void setup() {
// put your setup code here, to run once:
//Serial.begin(115200);//USBCDC输出
Serial1.setPins(44, 43, -1, -1);//修改指定引脚
Serial1.begin(115200);//uart1:TXD1:GPIO16,RXD1:GPIO15
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
}
void loop() {
// put your main code here, to run repeatedly:
Serial1.println("Hello World");
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
delay(1000);
}
- 🔖platformio.ini
[env:4d_systems_esp32s3_gen4_r8n16]
platform = espressif32
board = 4d_systems_esp32s3_gen4_r8n16
framework = arduino
后记
- 对于N16R8型号的ESP32S3模组,在·VSCode PlatformIO环境下,推荐选择
4d_systems_esp32s3_gen4_r8n16
,默认启用了psram。