ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

arduino-esp32 USB API 完全指南:在 ESP32-S2/S3 上使用 TinyUSB 实现设备与主机模式

2026/9/13 20:01:26 拓冰建站 浏览量
arduino-esp32 USB API 完全指南:在 ESP32-S2/S3 上使用 TinyUSB 实现设备与主机模式 arduino-esp32 USB API 完全指南在 ESP32-S2/S3 上使用 TinyUSB 实现设备与主机模式【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32导读本文围绕 arduino-esp32 核心库的 USB API 文档系统讲解如何在带 USB 外设的 ESP32 芯片如 ESP32-S2、ESP32-S3上通过 Arduino 接口配置和使用 USB 功能。你将掌握统一的ESPUSB类 API全局对象USB的每个配置项VID/PID、版本号、类信息、WebUSB、DFU 等、事件回调机制以及它与 USB CDC虚拟串口、USB MSCU 盘等子类的配合方式并能在自己的工程中直接落地基于 TinyUSB 的 USB 设备应用。一、适用范围与背景哪些芯片支持这套 USB APIUSBUniversal Serial Bus是设备之间交换数据的通用外设总线。在 arduino-esp32 中USB 功能基于 TinyUSB 实现并支持device设备与host主机两种模式USB as Device设备模式ESP32 作为 USB 设备如鼠标、键盘连接到计算机或手机等主机上。USB as Host主机模式ESP32 作为主机外接调制解调器、鼠标、键盘等设备。官方文档明确指出该模式在 ESP32 上仍处于开发阶段This mode is still under development for the ESP32因此实际使用中应以设备模式为主。重要限制这套 API 仅支持带有 USB 外设USB-OTG的芯片典型代表是 ESP32-S2 和 ESP32-S3。而像 ESP32-C3 这类芯片自带的是 native CDCJTAG 外设不在本文档描述范围内需使用 USB CDC 中针对 CDC 的实现或默认的 HardwareSerial 方案。从源码层面看这一限制体现在 cores/esp32/USB.h 的编译守卫中#include soc/soc_caps.h #if SOC_USB_OTG_SUPPORTED #include sdkconfig.h #if CONFIG_TINYUSB_ENABLED即只有芯片 SOC 能力支持 USB-OTG且在 menuconfig 中启用了CONFIG_TINYUSB_ENABLED时ESPUSB类与全局对象USB才会被编译进来。二、USB Common统一的设备描述配置 API文档将各 USB 设备类CDC、MSC、HID 等共用的配置项统一命名为USB Common全部由全局对象ESPUSB USB提供声明见 cores/esp32/USB.h。以下是全部 API 的签名、默认值与源码实现说明。2.1 onEvent —— 事件回调注册事件处理函数用于设置回调有两种重载形式void onEvent(esp_event_handler_t callback); // 监听所有 USB 事件 void onEvent(arduino_usb_event_t event, esp_event_handler_t callback); // 监听指定事件其中event可取以下枚举值定义于 cores/esp32/USB.h事件含义ARDUINO_USB_ANY_EVENT任意事件内部值为ESP_EVENT_ANY_IDARDUINO_USB_STARTED_EVENTUSB 设备已挂载mounted/configuredARDUINO_USB_STOPPED_EVENTUSB 设备已卸载unmountedARDUINO_USB_SUSPEND_EVENTUSB 总线挂起ARDUINO_USB_RESUME_EVENTUSB 总线恢复ARDUINO_USB_MAX_EVENT事件计数上限标记用源码级原理USB 事件基于 ESP-IDF 的esp_event机制实现。构造ESPUSB时会在 USB.cpp 中创建名为arduino_usb_events的专用事件循环队列长度 5任务优先级与栈大小分别取自ARDUINO_SERIAL_EVENT_TASK_PRIORITY和ARDUINO_SERIAL_EVENT_TASK_STACK_SIZEonEvent内部调用arduino_usb_event_handler_register_with()把回调注册到ARDUINO_USB_EVENTS事件基上USB.cpp。事件本身由 TinyUSB 回调触发——tud_mount_cb发STARTED_EVENT、tud_umount_cb发STOPPED_EVENT、tud_suspend_cb发SUSPEND_EVENT携带remote_wakeup_en标志、tud_resume_cb发RESUME_EVENT见 USB.cpp。回调事件数据通过arduino_usb_event_data_t联合体传递目前包含suspend.remote_wakeup_en字段。2.2 VID / PID —— 厂商与产品标识VIDVendor ID16 位厂商标识用于识别产品所属公司。注意官方文档强调不能自行随意定义 VID若需要专属 VID 必须向 USB-IF 购买。bool VID(uint16_t v); // 设置返回是否成功尚未 begin 时返回 true uint16_t VID(void); // 读取默认 VID 为0x303A乐鑫 Espressif 的 VID见 USB.cpp 的USB_ESPRESSIF_VID宏。PIDProduct ID16 位产品标识用于识别具体产品型号。bool PID(uint16_t p); uint16_t PID(void);默认 PID 为0x0002USB.cpp 中USB_PID宏。2.3 firmwareVersion —— 固件版本16 位无符号固件版本号bool firmwareVersion(uint16_t version); uint16_t firmwareVersion(void);默认值0x100对应源码构造列表中的fw_version(0x0100)USB.cpp。2.4 usbVersion —— USB 协议版本bool usbVersion(uint16_t version); uint16_t usbVersion(void);默认值0x200即 USB 2.0。源码注释提示如需启用 BOSBinary Device Object Store描述符与 WebUSB版本号应至少为 2.10x210或 3.xUSB.cpp。2.5 usbPower —— 电流声明mAbool usbPower(uint16_t mA); uint16_t usbPower(void);默认值0x500500 mA。文档特别说明该配置只写入 USB 设备描述信息不会改变物理电源输出。2.6 usbClass / usbSubClass / usbProtocol —— 设备类别分别设置 USB 设备类、子类和协议bDeviceClass / bDeviceSubClass / bDeviceProtocolbool usbClass(uint8_t _class); uint8_t usbClass(void); bool usbSubClass(uint8_t subClass); uint8_t usbSubClass(void); bool usbProtocol(uint8_t protocol); uint8_t usbProtocol(void);默认值分别为TUSB_CLASS_MISC、MISC_SUBCLASS_COMMON、MISC_PROTOCOL_IADIAD即 Interface Association Descriptor常用于复合设备对应源码构造列表USB.cpp。2.7 usbAttributes —— 配置描述符属性bool usbAttributes(uint8_t attr); uint8_t usbAttributes(void);默认值TUSB_DESC_CONFIG_ATT_SELF_POWERED自供电标志。2.8 webUSB / webUSBURL —— WebUSB 支持webUSB(bool enabled)用于启用/禁用 WebUSB 功能webUSB()用于查询当前开关状态。源码中有一个细节一旦启用 WebUSB 且当前usb_version 0x0210会自动把usb_version提升到 0x0210USB.cpp因为 WebUSB 依赖 BOS 描述符要求 USB 2.1。bool webUSB(bool enabled); bool webUSB(void);webUSBURL用于定义 WebUSB 落地页 URL设备描述符中会携带该链接浏览器可据此打开页面bool webUSBURL(const char * name); const char * webUSBURL(void);默认 URL 为 https://docs.espressif.com/projects/arduino-esp32/en/latest/_static/webusb.html源码宏USB_WEBUSB_URLUSB.cpp。仓库中对应页面文件位于 docs/_static/webusb.html。2.9 productName / manufacturerName / serialNumber —— 字符串描述符bool productName(const char * name); const char * productName(void); bool manufacturerName(const char * name); const char * manufacturerName(void); bool serialNumber(const char * name); const char * serialNumber(void);默认值制造商Espressif Systems宏USB_MANUFACTURER产品名ARDUINO_BOARD编译时由 boards.txt 注入的开发板名称序列号0但在 ESP32-S3 上若保持默认宏__MAC__begin()时会读取 eFuse 中的默认 MAC格式化为 12 位十六进制字符串作为序列号USB.cpp。2.10 enableDFU —— DFU 能力bool enableDFU();用于启用 DFUDevice Firmware Upgrade能力。源码中根据编译宏分两条路径实现USB.cppCFG_TUD_DFU注册 OTA DFU 描述符load_dfu_ota_descriptorCFG_TUD_DFU_RUNTIME注册 Runtime DFU 描述符并实现tud_dfu_runtime_reboot_to_dfu_cb()——收到主机端 DFU_DETACH 请求后调用usb_persist_restart(RESTART_BOOTLOADER_DFU)重启进入 bootloaderUSB.cpp。两者都未启用时返回false。2.11 begin —— 启动 USBbool begin();使用当前配置默认值或此前设置的值启动 USB 外设bool begin();从源码看begin()会把所有配置字段打包进tinyusb_device_config_t调用tinyusb_init()完成初始化成功后_started置位USB.cpp。ESPUSB还重载了operator bool()返回_started tinyusb_device_mounted——即设备已启动且已成功挂载到主机可作为if (USB)的判断条件。一个重要的使用约定所有 setter如VID()、PID()、productName()等只有在!_started尚未调用begin()时才会生效返回值即表示设置是否成功。因此必须先配置、后 begin。三、配置项速查表API设置读取默认值备注onEvent注册回调——可监听全部或指定事件VIDbool VID(uint16_t)uint16_t0x303A需向 USB-IF 购买PIDbool PID(uint16_t)uint16_t0x0002—firmwareVersionbooluint16_t0x10016 位固件版本usbVersionbooluint16_t0x200(USB 2.0)WebUSB 需 ≥0x210usbPowerbool usbPower(mA)uint16_t0x500(500mA)仅描述信息usbClassbooluint8_tTUSB_CLASS_MISC—usbSubClassbooluint8_tMISC_SUBCLASS_COMMON—usbProtocolbooluint8_tMISC_PROTOCOL_IAD复合设备常用usbAttributesbooluint8_tTUSB_DESC_CONFIG_ATT_SELF_POWERED—webUSBbool webUSB(enabled)bool关闭false启用时自动提升 usbVersionproductNameboolconst char *ARDUINO_BOARD—manufacturerNameboolconst char *Espressif Systems—serialNumberboolconst char *0S3 默认 MACS3 默认__MAC__→ 实际 MACwebUSBURLboolconst char *docs.espressif.com 默认页—enableDFU启用 DFU 接口—视编译宏Runtime DFU 支持 DETACH 重启begin启动 USB——需在所有 setter 之后调用四、完整示例事件处理 复合设备官方示例 libraries/USB/examples/CompositeDevice/CompositeDevice.ino 展示了 USB Common API 与各设备类的组合用法其中事件回调的写法可以直接复用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, contenteditable="false">【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考