【学习记录】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才能烧录。

相关推荐
我命由我123451 小时前
Photoshop - Photoshop 使用魔棒工具选择单独的区域
学习·ui·职场和发展·求职招聘·职场发展·学习方法·photoshop
JWASX1 小时前
Java 转 go 学习 - kitex(1)
学习·golang
li星野2 小时前
HAVE — have / has / had (One-Page Notes)
学习
传奇开心果编程2 小时前
【声明式UI开发实用技术学与练】第8课 状态提升与下放
学习·flutter·react native·ui·swiftui·composer
阳光九叶草LXGZXJ10 小时前
达梦数据库-报错-15-列【XXX】长度超出定义
linux·运维·数据库·sql·学习
mlidongfeng13 小时前
【学习】mKernel 分析
学习
一只小小的芙厨14 小时前
【线性DP】
学习·算法·动态规划
li星野15 小时前
DO — Auxiliary Verb (One-Page Notes)
学习
minglie115 小时前
关系的有向管道模型
学习