【学习记录】USB连接与枚举全解析:从D+/D-上拉到pyOCD烧录

【学习记录】USB连接与枚举全解析:从D+/D-上拉到pyOCD烧录

在嵌入式开发中,USB是最常用的通信接口之一。但很多工程师只知道"插上USB线就能用",却不清楚主机是如何识别设备、判断速度、完成枚举的。本文从D+/D-上拉电阻讲起,完整拆解USB速度检测、chirp握手、枚举流程,并结合CMSIS-DAP调试器和pyOCD烧录场景,给出实战排查指南。


📌 目录

  1. 一句话结论(#一 一句话结论)
  2. USB速度等级与D+/D-的决定作用
  3. 高速设备握手过程
  4. 电脑枚举流程
  5. Windows下查看速度和枚举状态
  6. [CMSIS-DAP / pyOCD场景补充](#CMSIS-DAP / pyOCD场景补充)
  7. 常见故障与排查
  8. 总结

一、一句话结论

USB连接后,主机先靠设备端的D+/D-上拉电阻判断"低速还是全速";如果是高速设备,再通过chirp握手切到高速。枚举则是主机通过控制端点0读取描述符、分配地址、加载驱动,最终让设备可用。


二、USB速度等级与D+/D-的决定作用

USB 2.0有三种速度:

速度 速率 设备端上拉 典型设备
低速 Low Speed 1.5 Mbps D- 上拉 1.5kΩ 键盘、鼠标
全速 Full Speed 12 Mbps D+ 上拉 1.5kΩ CMSIS-DAP、HID、音频
高速 High Speed 480 Mbps 先 D+ 上拉,握手后切高速 U盘、高速采集卡

主机端D+/D-各有15kΩ下拉。设备插入后:

  • 若主机检测到 D-被拉高 → 低速设备;
  • 若检测到 D+被拉高 → 全速设备;
  • 若D+上拉后,主机复位期间发chirp,设备回应 → 切到高速;
  • 主机不支持高速,或设备不支持,就保持全速。

⚠️ 注意:高速设备不是靠D+/D-直接决定,而是"先以全速身份出现,再握手升级"。USB 3.0有独立TX/RX引脚,不靠D+/D-判断超速。

硬件原理图检查要点:

  • D+上拉1.5kΩ(全速)或D-上拉1.5kΩ(低速)
  • 主机端15kΩ下拉(通常在Hub或主控内部)
  • 上拉电阻必须连接到3.3V(不能接5V,否则可能损坏芯片)

三、高速设备握手过程

高速设备的握手流程如下:

  1. 设备插入,D+上拉,主机识别为全速。
  2. 主机发总线复位(SE0)。
  3. 主机发chirp K。
  4. 设备回chirp K/J序列。
  5. 双方切换高速终端,D+上拉断开。
  6. 之后进入高速通信。

主机 USB设备 主机 USB设备 #mermaid-svg-QYccyq6vtkbeACJa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QYccyq6vtkbeACJa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QYccyq6vtkbeACJa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QYccyq6vtkbeACJa .error-icon{fill:#552222;}#mermaid-svg-QYccyq6vtkbeACJa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QYccyq6vtkbeACJa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QYccyq6vtkbeACJa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QYccyq6vtkbeACJa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QYccyq6vtkbeACJa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QYccyq6vtkbeACJa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QYccyq6vtkbeACJa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QYccyq6vtkbeACJa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QYccyq6vtkbeACJa .marker.cross{stroke:#333333;}#mermaid-svg-QYccyq6vtkbeACJa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QYccyq6vtkbeACJa p{margin:0;}#mermaid-svg-QYccyq6vtkbeACJa .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-QYccyq6vtkbeACJa text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-QYccyq6vtkbeACJa .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-QYccyq6vtkbeACJa .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-QYccyq6vtkbeACJa .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-QYccyq6vtkbeACJa .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-QYccyq6vtkbeACJa #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-QYccyq6vtkbeACJa .sequenceNumber{fill:white;}#mermaid-svg-QYccyq6vtkbeACJa #sequencenumber{fill:#333;}#mermaid-svg-QYccyq6vtkbeACJa #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-QYccyq6vtkbeACJa .messageText{fill:#333;stroke:none;}#mermaid-svg-QYccyq6vtkbeACJa .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-QYccyq6vtkbeACJa .labelText,#mermaid-svg-QYccyq6vtkbeACJa .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-QYccyq6vtkbeACJa .loopText,#mermaid-svg-QYccyq6vtkbeACJa .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-QYccyq6vtkbeACJa .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-QYccyq6vtkbeACJa .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-QYccyq6vtkbeACJa .noteText,#mermaid-svg-QYccyq6vtkbeACJa .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-QYccyq6vtkbeACJa .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-QYccyq6vtkbeACJa .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-QYccyq6vtkbeACJa .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-QYccyq6vtkbeACJa .actorPopupMenu{position:absolute;}#mermaid-svg-QYccyq6vtkbeACJa .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-QYccyq6vtkbeACJa .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-QYccyq6vtkbeACJa .actor-man circle,#mermaid-svg-QYccyq6vtkbeACJa line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-QYccyq6vtkbeACJa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 双方切换高速终端 进入高速通信 D+上拉(识别为全速) 总线复位(SE0) chirp K chirp K/J序列 断开D+上拉

如果这步失败,设备就停留在全速。

💡 实战提示 :CMSIS-DAP调试器绝大多数是全速12Mbps,足够烧录和调试。 不要盲目追求高速,全速对调试器来说完全够用。


四、电脑枚举流程

枚举就是主机"问清楚你是谁、怎么用你"的过程:

步骤 动作 说明
1 检测连接 主机看到D+/D-上拉,确认有设备
2 端口供电 给VBUS 5V,等待稳定
3 总线复位 设备进入默认状态,地址0,端点0
4 读设备描述符前8字节 获取 bMaxPacketSize0
5 分配地址 SET_ADDRESS,设备获得唯一地址
6 读完整设备描述符 18字节,含VID、PID、类代码
7 读配置描述符 接口、端点、供电方式
8 读字符串描述符 厂商、产品、序列号
9 选择配置 SET_CONFIGURATION,设备进入工作状态
10 加载驱动 Windows根据VID/PID/类匹配HID、WinUSB、CDC等
11 设备就绪 应用层可通信

枚举失败常见提示:

  • "未知USB设备(设备描述符请求失败)"
  • "无法识别的USB设备"
  • 设备反复插拔声

💡 枚举的本质 :主机通过控制端点0(Endpoint 0)与设备通信,读取各种描述符,最终确定设备的身份和使用方式。


五、Windows下查看速度和枚举状态

方法 作用
USB Device Tree Viewer(UsbTreeView) 最直观,显示Low/Full/High Speed、VID/PID、描述符
设备管理器 看是否识别、有无黄色感叹号
USBView 微软官方工具,查看USB拓扑和描述符
Wireshark + USBPcap 抓枚举包,分析控制传输
示波器/逻辑分析仪 测D+/D-静态电平:全速D+≈3.3V,D-≈0V;低速相反

Linux下:

bash 复制代码
lsusb -t        # 显示 480M/12M/1.5M
dmesg | grep usb

示波器测量方法:

  • 全速设备:D+约3.3V,D-约0V
  • 低速设备:D-约3.3V,D+约0V
  • 高速设备:静态时两者都接近0V(因为上拉已断开)

六、CMSIS-DAP / pyOCD场景补充

  • CMSIS-DAP调试器通常是全速USB HID或WinUSB设备。
  • python -m pyocd list 能看到调试器,前提是USB枚举成功且驱动匹配。
  • 如果 pyocd list 为空,先看设备管理器:
设备管理器状态 可能原因 排查方向
有"未知USB设备" 枚举失败 查D+上拉、晶振、USB走线、供电
有HID/WinUSB设备但pyOCD不识别 驱动或VID/PID问题 查VID/PID、CMSIS-DAP固件、驱动

⚠️ 芯片限制 :STM32F103只有全速USB,不能跑高速;STM32F4的OTG_HS需外接ULPI PHY才能480Mbps。

pyOCD调试流程:

复制代码
USB枚举成功 → 驱动匹配 → pyOCD识别设备 → 烧录/调试

任何一环失败,pyOCD都会显示"找不到设备"。


七、常见故障与排查

现象 可能原因 排查方法
电脑无反应 D+无上拉、VBUS未到、USB线只供电 测D+电压、换线
低速被识别 D-上拉,或D+/D-接反 查原理图、测上拉位置
未知设备 枚举失败、描述符错误、时钟不准 UsbTreeView看描述符、查晶振
反复重连 供电不足、看门狗复位、中断阻塞 测5V/3.3V、查固件
pyOCD找不到 驱动未装、VID/PID不对 设备管理器、换HID/WinUSB模式

排查思路总结:

  1. 先看硬件:D+/D-上拉是否正确,VBUS是否到位,晶振是否起振。
  2. 再看枚举:用UsbTreeView确认是否识别为全速设备,描述符是否正常。
  3. 最后看驱动:设备管理器确认驱动是否加载,pyOCD是否匹配。

八、总结

阶段 核心动作 关键点
速度检测 D+/D-上拉决定低速/全速 全速D+上拉1.5kΩ,低速D-上拉1.5kΩ
高速握手 chirp K/J序列 失败则停留在全速
枚举 读描述符、分配地址、加载驱动 控制端点0是关键通道
调试器 CMSIS-DAP通常是全速设备 枚举成功+驱动匹配=pyOCD可用

一句话总结:D+/D-上拉决定低速/全速,高速靠chirp握手;电脑枚举就是读描述符、分配地址、装驱动。调试器枚举成功,pyOCD才能烧录。

相关推荐
zhangrelay9 小时前
新版|-|单片机原理与接口技术-2026持续改进优化-从MEGA2560-ESP32与Wokwi到ROS2-Lyrical与具身智能栈
笔记·单片机·嵌入式硬件·学习
叼烟扛炮12 小时前
Linux 学习笔记(三十三):线程互斥——互斥锁(Mutex)与死锁
linux·运维·服务器·笔记·学习·1024程序员节
m4Rk_14 小时前
【论文阅读】Agent 记忆机制(113):Agentic Memory Management——从“检索相关信息”走向“管理 Agent 内部记忆”
论文阅读·人工智能·学习·开源·github
辣知15 小时前
辣知·化智92 《山海经》里的史前密码
学习
鬼手点金15 小时前
KV Cache 未必是一次性的:可编辑、可组合的“笔记”
java·人工智能·笔记·学习·自动化·1024程序员节
kyrie_sakura17 小时前
大模型学习18 大模型学习 - LangChain2_Model I/O
学习·自然语言处理
宝绿特塑业再生科技17 小时前
板材收缩率不稳,户外家具装配尺寸为何对不上:从切割尺寸变化到接缝不一的系统性排查与对策
笔记·科技·学习·生活·户外家具·hdpe再生颗粒·hdpe
~城南花已开~18 小时前
Intel E810 SR-IOV VF Spoofcheck 防伪造测试-KVM3
服务器·网络·笔记·学习·ubuntu·etl工程师
我命由我1234520 小时前
6-3.Python 异常处理 - 异常处理进阶(else 块与 finally 块、异常传递、自定义异常)
开发语言·前端·数据库·后端·python·学习·java-ee
外收内放20 小时前
FastAPI猜字谜实战(8):收官
开发语言·python·学习·fastapi