、为什么要学习 USB 协议USB 是 Universal Serial Bus 的缩写中文通常叫通用串行总线。它是电脑、手机、工控机、单片机开发板和各种外设之间最常见的连接方式之一。在嵌入式开发中USB 常用于虚拟串口通信U 盘读写键盘、鼠标、按键板固件升级数据采集音频设备摄像头设备USB 网卡上位机参数配置很多初学者第一次接触 USB 时会觉得它很复杂因为 USB 不像普通 UART 那样“发字节、收字节”就结束了。USB 设备接入电脑后电脑会先询问设备是什么、支持什么功能、需要多少电流、有哪些接口、有哪些端点然后才开始真正传输数据。这个“先自我介绍再通信”的过程就是 USB 学习的核心。二、USB 通信中的基本角色USB 通信中最重要的两个角色是主机Host设备Device1. 主机是什么USB 主机是整个 USB 总线的管理者。它负责供电、检测设备插入、发起通信、读取描述符、分配地址、配置设备、调度数据传输。常见 USB 主机包括电脑工控机手机 OTG 模式支持 USB Host 的 MCU嵌入式 Linux 主板USB 通信中绝大多数数据传输都是由主机主动发起的。即使设备想发送数据也通常需要等主机来询问或调度。2. 设备是什么USB 设备是被主机管理的外设。它连接到主机后需要按照 USB 协议回答主机的问题。常见 USB 设备包括U 盘键盘鼠标USB 转串口模块USB 摄像头USB 声卡单片机 USB CDC 虚拟串口设备STM32F103C8T6 使用 CherryUSB 做 CDC 虚拟串口时STM32 就是 USB Device电脑就是 USB Host。三、什么是 USB 端口很多人会把“端口”理解成电脑上的 USB 插孔这在日常语言里没有问题。但在 USB 协议学习中需要区分两种概念物理端口逻辑端点1. 物理端口物理端口就是看得见摸得着的 USB 接口例如电脑上的 USB-A、USB-C 插口或者开发板上的 Micro USB、Type-C 接口。它负责电气连接常见信号包括VBUSUSB 供电通常是 5 VGND地DUSB 全速/低速数据信号D-USB 全速/低速数据信号对于 STM32F103C8T6 的 USB FS 设备PA11 是 USB_DM也就是 D-PA12 是 USB_DP也就是 DUSB 全速设备通常通过 D 上拉电阻告诉主机“有一个全速 USB 设备接入了”。2. 逻辑端点USB 协议里更常说的是 Endpoint中文叫端点。端点不是物理插口而是设备内部用于数据传输的逻辑通道。可以把 USB 设备想象成一栋办公楼USB 设备是整栋楼接口 Interface 是不同部门端点 Endpoint 是每个部门收发文件的窗口电脑并不是随便往设备里写数据而是往某个端点发送数据或者从某个端点读取数据。四、USB 速度等级USB 有不同速度等级常见如下速度等级英文速率常见应用低速Low Speed1.5 Mbps鼠标、键盘全速Full Speed12 MbpsCDC、HID、普通 MCU USB高速High Speed480 MbpsU 盘、摄像头、网卡超高速SuperSpeed5 Gbps 及以上高速存储、扩展坞STM32F103C8T6 内置的是 USB Full Speed Device 控制器速率是 12 Mbps。它不能直接做 USB High Speed。USB 全速设备必须有准确的 48 MHz USB 时钟。对于 STM32F103常见配置是外部 HSE 8 MHzPLL 倍频到 72 MHzUSB 时钟使用 PLL / 1.5得到 48 MHz如果 USB 时钟不准电脑可能出现无法识别、设备描述符请求失败、Code 43 等问题。五、USB 连接后的枚举过程USB 设备插入电脑后不能马上开始业务通信。主机会先执行一个过程叫枚举 Enumeration。枚举可以理解为主机对设备进行“身份调查”和“建档登记”。典型枚举流程如下主机检测到 D 或 D- 上拉知道有设备接入。主机复位 USB 总线。设备进入默认地址0。主机读取设备描述符前 8 字节知道端点 0 最大包长。主机给设备分配一个新的 USB 地址。主机读取完整设备描述符。主机读取配置描述符。主机读取接口、端点、字符串等描述符。主机根据描述符加载对应驱动。主机设置配置设备进入可用状态。如果某一步失败Windows 可能提示请求 USB 设备描述符失败未知 USB 设备设备无法启动代码 10Windows 已将其停止代码 43其中“请求 USB 设备描述符失败”通常说明设备在枚举最早期就没有正确返回 Device Descriptor。六、什么是描述符描述符 Descriptor 是 USB 设备给主机看的“说明书”。主机通过描述符了解设备是什么、有哪些功能、如何通信。USB 设备必须正确提供描述符否则主机不知道该加载什么驱动也不知道如何访问设备。常见描述符包括设备描述符 Device Descriptor配置描述符 Configuration Descriptor接口描述符 Interface Descriptor端点描述符 Endpoint Descriptor字符串描述符 String Descriptor类特定描述符 Class-Specific Descriptor1. 设备描述符设备描述符说明整个 USB 设备的基本身份。它包含的信息通常有USB 协议版本设备类别VID厂商 IDPID产品 ID设备版本号厂商字符串索引产品字符串索引序列号字符串索引支持多少个配置例如 CDC 虚拟串口设备会通过设备描述符告诉电脑“我是一个 USB 设备我的 VID/PID 是多少我有一个配置。”如果设备描述符返回失败Windows 就可能报“请求 USB 设备描述符失败”。2. 配置描述符一个 USB 设备可以有一个或多个配置。配置描述符说明某个配置下设备需要多少电流、包含多少接口。配置描述符里常见字段包括配置总长度接口数量配置编号供电方式最大电流普通 MCU USB 设备通常只有一个配置。3. 接口描述符接口 Interface 表示设备的一个功能单元。例如HID 键盘有一个键盘接口U 盘有一个 MSC 接口CDC 虚拟串口通常有两个接口通信控制接口数据接口接口描述符告诉主机这是第几个接口接口属于哪个 USB 类这个接口有几个端点这个接口使用什么协议主机通常根据接口类别加载驱动。例如看到 HID 类就加载 HID 驱动看到 CDC ACM 类就加载虚拟串口相关驱动。4. 端点描述符端点描述符说明一个端点的传输方向、传输类型、最大包长和轮询间隔。端点描述符常见字段包括端点地址传输类型最大包长轮询间隔端点地址中最高位表示方向0x01端点 1 OUT主机到设备0x81端点 1 IN设备到主机0x02端点 2 OUT主机到设备0x83端点 3 IN设备到主机注意IN 和 OUT 是以主机为视角定义的。IN主机从设备读取数据OUT主机向设备发送数据这点对初学者很容易反。比如0x81是 IN 端点意思是设备通过这个端点把数据发给主机。5. 字符串描述符字符串描述符用于显示人类可读的信息例如厂商名称产品名称序列号例如在 Windows 设备管理器里看到的设备名称可能就来自产品字符串。在嵌入式 USB 协议栈中字符串描述符通常需要以 UTF-16LE 格式返回。很多协议栈允许开发者写 ASCII 字符串再自动转换成 USB 字符串描述符。如果直接写 UTF-8 中文而协议栈只按单字节 ASCII 转换就可能显示乱码。七、什么是端点 0端点 0 是 USB 设备必须具备的默认控制端点。它非常重要因为枚举过程基本都依赖端点 0 完成。端点 0 用于接收标准请求返回设备描述符返回配置描述符设置设备地址设置配置处理类请求处理厂商自定义请求端点 0 是双向控制端点既能 IN也能 OUT。如果端点 0 不能正常工作USB 设备通常无法枚举成功。八、USB 传输类型USB 有四种基本传输类型控制传输 Control Transfer批量传输 Bulk Transfer中断传输 Interrupt Transfer同步传输 Isochronous Transfer1. 控制传输控制传输主要用于设备管理和枚举端点 0 默认使用控制传输。典型用途获取描述符设置地址设置配置获取设备状态发送类请求控制传输可靠性高有明确的请求、数据和状态阶段。2. 批量传输批量传输适合大量可靠数据传输但不保证固定延时。典型用途U 盘数据读写USB 打印机CDC 虚拟串口数据收发大块普通数据传输CDC ACM 虚拟串口的数据端点通常使用 Bulk 传输。3. 中断传输中断传输适合小数据量、低延迟、周期性查询的场景。典型用途键盘鼠标HID 设备CDC 通知端点这里的“中断”不是 MCU 中断的意思而是 USB 协议中的一种传输调度方式。4. 同步传输同步传输适合实时数据流强调固定带宽和实时性但错误重传能力较弱。典型用途USB 音频USB 视频例如 USB 麦克风和摄像头通常会用到同步传输。九、USB 类 ClassUSB Class 是 USB 官方定义的一类标准设备功能。主机操作系统可以根据 Class 加载通用驱动。常见 USB Class类名作用常见设备CDC通信设备类虚拟串口、调制解调器HID人机接口设备类键盘、鼠标、自定义 HIDMSC大容量存储类U 盘、读卡器DFU固件升级类USB 升级设备Audio音频类USB 声卡、麦克风Video视频类USB 摄像头RNDIS/ECM/NCMUSB 网络类USB 网卡使用标准 Class 的好处是电脑端通常已有驱动开发者不需要自己写 Windows 驱动。十、以 CDC 虚拟串口为例理解 USB 结构CDC ACM 虚拟串口是 MCU 项目最常见的 USB 应用。一个 CDC ACM 设备通常包含1 个设备描述符1 个配置描述符2 个接口3 个端点1. 两个接口CDC ACM 通常有两个接口通信控制接口数据接口通信控制接口用于处理串口参数例如波特率、DTR、RTS 等。数据接口用于真正收发串口数据。2. 三个端点CDC ACM 常见端点中断 IN 端点通知串口状态Bulk OUT 端点主机发送数据给设备Bulk IN 端点设备发送数据给主机例如你的 STM32F103 CherryUSB 工程中0x83CDC 通知 IN 端点0x02CDC 数据 OUT 端点0x81CDC 数据 IN 端点当电脑串口助手发送数据时数据会通过 OUT 端点到达设备。当 MCU 回传数据时数据会通过 IN 端点发送给电脑。十一、USB 数据方向怎么理解USB 里的 IN 和 OUT 都是站在主机角度看的。这是 USB 初学者最容易混淆的地方。方向主机视角设备视角IN主机读取数据设备发送数据OUT主机写出数据设备接收数据所以CDC_IN_EP 0x81是设备发给电脑的数据通道CDC_OUT_EP 0x02是电脑发给设备的数据通道十二、USB 请求USB 主机会向设备发送请求 Request。请求通过端点 0 控制传输完成。请求大致分为标准请求类请求厂商自定义请求1. 标准请求标准请求是所有 USB 设备都需要支持的基础请求。常见标准请求GET_DESCRIPTOR获取描述符SET_ADDRESS设置设备地址SET_CONFIGURATION设置配置GET_STATUS获取状态CLEAR_FEATURE清除特性SET_FEATURE设置特性枚举过程主要依赖标准请求。2. 类请求类请求和具体 USB Class 有关。例如 CDC ACM 中常见类请求SET_LINE_CODING设置波特率、停止位、校验位、数据位GET_LINE_CODING获取串口参数SET_CONTROL_LINE_STATE设置 DTR、RTS虽然 CDC 是虚拟串口但 USB 传输本身并不真的依赖 UART 波特率。波特率更多是为了兼容传统串口软件的概念。3. 厂商自定义请求厂商自定义请求由开发者自己定义适合实现特殊控制功能。例如读取设备版本号设置设备参数进入升级模式控制 LED 或继电器读取内部状态自定义请求灵活但主机端也需要自己写对应程序。十三、VID 和 PIDVID 是 Vendor ID厂商 ID。PID 是 Product ID产品 ID。电脑通过 VID/PID 识别不同厂商和不同产品。正式量产产品应使用合法申请的 VID/PID。学习、测试和内部开发阶段可以使用示例 VID/PID但不要用于商业量产。如果多个不同设备使用相同 VID/PID 和相同序列号Windows 可能会把它们当作同一个设备导致驱动、COM 号或缓存状态混乱。十四、USB 供电和电气检测USB 接口通常提供 VBUS 5 V。设备可以从 USB 取电也可以自供电。描述符里会声明设备供电方式Bus Powered总线供电Self Powered自供电还会声明最大电流。例如配置描述符中写 100 mA主机就认为设备最大从 USB 取 100 mA。全速 USB 设备通过 D 上拉告诉主机设备接入。低速设备通过 D- 上拉告诉主机设备接入。STM32F103 做 USB 全速设备时关键硬件点是PA11 接 D-PA12 接 DUSB 时钟 48 MHzD 上拉正确USB 线是数据线不是纯充电线十五、为什么复位后要重新插拔 USB有些 STM32F103 开发板的 D 上拉电阻是固定接到 3.3 V 的。这样 MCU 软件复位时电脑并不会看到 USB 设备真正断开。结果是电脑还以为旧设备在线MCU 内部 USB 外设已经复位主机和设备状态不同步设备可能无法重新枚举解决办法是软件模拟断开。常见做法USB 初始化前将 PA12 配置为 GPIO 开漏输出。拉低 PA12 一小段时间例如 20 ms 到 100 ms。释放 PA12。初始化 USB 外设。主机检测到设备重新接入并重新枚举。这个过程相当于让 Windows 感知一次“拔出再插入”。十六、USB 协议栈做了什么USB 协议栈是帮开发者处理 USB 协议细节的软件模块。以 CherryUSB 为例它通常负责处理 USB 标准请求管理设备描述符管理配置、接口和端点处理端点 0 控制传输处理 CDC、HID、MSC 等类请求调用底层 USB 控制器驱动收发数据在 USB 事件发生时通知应用层开发者通常只需要关心写好描述符注册接口和端点处理接收回调调用发送接口实现业务协议底层寄存器、端点状态、枚举细节由协议栈处理。十七、USB Device 开发常见错误1. USB 时钟错误USB 全速设备需要 48 MHz。时钟错误会导致枚举失败。2. D 和 D- 接反PA11 是 D-PA12 是 D。接反后主机无法正常识别。3. D 上拉问题没有上拉主机检测不到设备。固定上拉则可能导致复位后不能重新枚举。4. 描述符长度错误配置描述符总长度、接口数量、端点数量不匹配可能导致枚举失败或驱动加载异常。5. 端点地址不一致代码里使用的端点地址必须和描述符里的端点地址一致。6. 中断没有进入协议栈USB 中断没有调用协议栈处理函数设备无法响应主机请求。7. HAL USB 库和第三方协议栈同时操作外设例如同时调用 STM32 HAL PCD 和 CherryUSB会导致 USB 寄存器状态冲突。8. 字符串描述符编码错误ASCII 通常安全。中文需要确保协议栈正确转换为 UTF-16LE。9. PMA/FIFO 配置错误对于 STM32 FSDEVPMA 是 USB 专用包缓冲区。PMA 访问方式、端点缓冲区分配错误会导致设备描述符或数据传输异常。十八、学习 USB 的推荐路线建议初学者按以下顺序学习理解 Host 和 Device。理解枚举过程。理解描述符。理解端点和 IN/OUT 方向。理解四种传输类型。先做 CDC 虚拟串口。再做 HID 自定义设备。最后学习 MSC、DFU、Audio、Video 等复杂类。对于 STM32F103 和 CherryUSB最推荐从 CDC ACM 虚拟串口开始因为它能同时覆盖设备描述符配置描述符接口描述符端点描述符控制传输Bulk 传输类请求主机驱动加载应用层数据收发十九、用一句话理解 USBUSB 不是简单的串口线而是一套由主机统一管理的分层通信协议。设备接入后先通过描述符告诉主机“我是谁、我有什么功能、你该怎么和我通信”主机完成枚举和驱动加载后双方才通过端点进行真正的数据传输。如果能理解“主机、设备、枚举、描述符、接口、端点、传输类型”这几个核心概念就已经掌握了 USB 协议入门最重要的骨架