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),仅供参考

相关新闻

Figma 变量创建指南:从源 Token 数据到语义化变量体系的建模与落地(基于 figma-use Skill 实践)

Figma 变量创建指南:从源 Token 数据到语义化变量体系的建模与落地(基于 figma-use Skill 实践)

Figma 变量创建指南:从源 Token 数据到语义化变量体系的建模与落地(基于 figma-use Skill 实践) 【免费下载链接】skills Skills Catalog for Codex 项目地址: https://gitcode.com/GitHub_Trending/skills4/skills 本篇指南聚焦于「如…

2026/9/13 20:01:26 阅读更多 →
CAN自定义协议设计实战:从ID规划到量产落地

CAN自定义协议设计实战:从ID规划到量产落地

1. 为什么“CAN自定义协议”不是写个ID和数据就完事——从汽车ECU通信现场说起我第一次在整车厂做CAN通信调试时,被一个看似简单的“灯光控制报文”卡了整整三天。客户要求用标准帧ID 0x123发送4字节数据:前两字节控制近光灯/远光灯开关,后两…

2026/9/13 20:01:26 阅读更多 →
STM32F103+EC800-4G裸机实现GNSS定位与ONENET直传

STM32F103+EC800-4G裸机实现GNSS定位与ONENET直传

简介:本资源是一套面向嵌入式物联网开发者的STM32F103单片机实战项目例程,聚焦于GNSS定位与多传感器数据采集、4G远程通信及云平台双向交互,适用于高校电子类课程设计、毕业设计及工程师快速原型开发。压缩包共245个文件,含40余个…

2026/9/13 20:01:26 阅读更多 →

最新新闻

wgpu 多窗口渲染实战:hello_windows 示例如何同时管理 16 个窗口与 Surface

wgpu 多窗口渲染实战:hello_windows 示例如何同时管理 16 个窗口与 Surface

wgpu 多窗口渲染实战:hello_windows 示例如何同时管理 16 个窗口与 Surface 【免费下载链接】wgpu A cross-platform, safe, pure-Rust graphics API. 项目地址: https://gitcode.com/GitHub_Trending/wg/wgpu 本篇指南围绕 wgpu 仓库中 examples/features 下…

2026/9/13 20:58:55 阅读更多 →
如何测试 Vector:高性能可观测性数据管道的测试策略全景

如何测试 Vector:高性能可观测性数据管道的测试策略全景

如何测试 Vector:高性能可观测性数据管道的测试策略全景 【免费下载链接】vector A high-performance observability data pipeline. 项目地址: https://gitcode.com/GitHub_Trending/vect/vector 本篇技术指南以 Vector 项目团队撰写的《How we test Vector…

2026/9/13 20:58:55 阅读更多 →
machine-learning-for-trading 第 21 章实战:用强化学习解决执行、做市与对冲的顺序决策问题

machine-learning-for-trading 第 21 章实战:用强化学习解决执行、做市与对冲的顺序决策问题

machine-learning-for-trading 第 21 章实战:用强化学习解决执行、做市与对冲的顺序决策问题 【免费下载链接】machine-learning-for-trading Code for Machine Learning for Trading, 3rd edition — from data sourcing to live execution. 项目地址: https://g…

2026/9/13 20:58:55 阅读更多 →
OmniRoute 弹性网关开发指南:请求管线、三层故障隔离机制与代码库扩展实践

OmniRoute 弹性网关开发指南:请求管线、三层故障隔离机制与代码库扩展实践

OmniRoute 弹性网关开发指南:请求管线、三层故障隔离机制与代码库扩展实践 【免费下载链接】OmniRoute Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works …

2026/9/13 20:58:55 阅读更多 →
Gemini API 安全设置与 Responsible AI 实战:使用 Safety Settings 精确控制内容过滤阈值

Gemini API 安全设置与 Responsible AI 实战:使用 Safety Settings 精确控制内容过滤阈值

Gemini API 安全设置与 Responsible AI 实战:使用 Safety Settings 精确控制内容过滤阈值 【免费下载链接】skills Agent Skills for Google products and technologies 项目地址: https://gitcode.com/GitHub_Trending/skills29/skills 本篇技术指南聚焦于 …

2026/9/13 20:58:55 阅读更多 →
开源思维导图 Simple Mind Map:5分钟跑通,结构随时切换

开源思维导图 Simple Mind Map:5分钟跑通,结构随时切换

开源思维导图 Simple Mind Map:5分钟跑通,结构随时切换 【免费下载链接】mind-map SimpleMindMap(思绪思维导图):一个强大的思维导图。A powerful mind map. 项目地址: https://gitcode.com/GitHub_Trending/mi/mind…

2026/9/13 20:57:54 阅读更多 →

日新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/13 0:00:24 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/13 0:00:24 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/13 0:00:24 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/13 0:00:24 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/13 0:00:24 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/13 0:00:24 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/13 16:51:11 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/12 18:29:34 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/12 19:02:44 阅读更多 →