第二章 OTG硬件连接与信号定义

做OTG驱动调试,第一关不是看代码,而是看板子上的那几个焊盘和电阻。硬件连接错了,驱动再怎么改也白搭。我早年接手一个项目,板子回来怎么都识别不了设备,查了一个礼拜才发现ID引脚的焊盘虚焊了。嗯,那次之后我就养成了习惯——先拿万用表量一遍信号,再碰软件。

2.1 认识OTG连接器

OTG物理层的核心是连接器。现在最常用的是Micro-AB,也有老一点的Mini-AB。别看插座小,里面5个引脚各司其职。我把它总结成一张表,你对照着看:

引脚号名称信号方向功能说明
1VBUS双向4.4V~5.25V供电
2D-双向USB差分数据负
3D+双向USB差分数据正
4ID输入(对设备)角色识别信号
5GND电源地回路

注意ID引脚只出现在OTG连接器里。标准USB-A或Micro-B没有它。你想想看,如果没有ID引脚,设备怎么知道自己该当Host还是Device?靠猜吗?不是,靠的就是这根信号线的电平。

Micro-AB插座内部机械结构也有讲究——插入方向不再区分正反,所以D+/D-的布局是左右对称的。实际PCB Layout时,D+和D-要等长走线、包地,差分布线更是基本功。我以前遇到客户打样回来的板子,D+走了15mm,D-走了22mm,结果高速信号眼图裂开,只能飞线救场。所以一开始就按规范来,不要图省事。

2.2 ID引脚与角色识别

ID引脚的工作原理,说白了就是一个电阻分压检测。OTG规范定义了三档:

  • ID接地(ID_GND):A端设备,作为Host。Micro-A插头内部将ID和GND短接。
  • ID悬空或高阻(ID_FLOAT):B端设备,作为Device。Micro-B插头不连接ID。
  • ID经电阻接地(ID_A):早期Mini-AB的扩展,现在基本不用了。

芯片内部是怎么检测的呢?大多数OTG控制器会在ID引脚上拉一个恒流源或弱上拉电阻(典型10kΩ~100kΩ),然后监测电压:

  • 如果检测到0V(接近地),判定为Host模式。
  • 如果检测到高电平(接近VDD),判定为Device模式。

这里有一个常见的坑:ID引脚的上拉电阻必须与芯片内部匹配。我曾经遇到过一块国产MCU,ID上拉电阻用的是10kΩ,但芯片内部检测阈值偏低,接上标准Micro-A插头后电压仍有0.7V,芯片死活认为自己是Device。调试时用示波器一抓,波形很干净,就是电平不对。最后换了个4.7kΩ上拉,问题解决。所以硬件设计时,建议你先看数据手册里的ID检测阈值,再选外部上拉电阻。

注意:ID线不能直接用GPIO直连插头,必须加ESD保护器件(TVS二极管),否则插拔瞬态放电会打坏控制器。

2.3 VBUS供电与电源管理

OTG设备需要具备供电角色切换能力。当作为Host时,VBUS必须输出5V(至少100mA,典型500mA)。当作为Device时,VBUS由外部Host提供。这就需要一个电源开关电路,通常是MOS管或专用负载开关(如TPS2051)。

我画了一个简化的供电拓扑图,你看看就明白了:

USB VBUS line
      |
      +---Load Switch (e.g., TPS2051)
      |       |
      |       +---EN (由GPIO控制, Host模式时拉高)
      |
      +---VBUS sense (ADC检测电压,用于判断是否连上Host)

电源开关的选型有几个关键点:

  • 最大连续电流:至少支持500mA,推荐1A以上余量。
  • 短路保护:防止VBUS被意外短路时烧板。
  • 反向电流阻断:OTG设备自身不供电时,不能反向漏电。

还要注意VBUS检测。我习惯在VBUS线上分压电阻接到ADC,实时监控有没有5V进来。如果检测到电压高于4V,就认为连接了一个Host,此时不能开启自身的供电开关,否则两个Host会打架,轻则烧保险,重则烧芯片。相信我,这种事情出过不止一次。

经验之谈:有些低成本方案直接把VBUS检测脚接到GPIO(通过电阻分压),不经过ADC。虽然可用,但扛不住电压波动。我在量产项目里要求必须用ADC,可以顺便监测过压、欠压,做保护。

2.4 D+/D-上拉与下拉电阻

USB设备插拔检测完全依赖D+/D-的电阻状态。OTG规范里,Host端在D+和D-上各接15kΩ下拉到地;Device端在D+(高速/全速)或D-(低速)上接1.5kΩ上拉到3.3V。这样当插入时,Host的D+或D-上就会被拉高,触发中断。

对于OTG设备来说,问题来了——它一会是Host,一会是Device,到底该接上拉还是下拉?答案是:动态切换。硬件上需要在D+/D-线上分别连接一个模拟开关或三态门,软件根据ID状态配置对应的上拉/下拉网络。

有些SoC内部已经集成了这部分,比如STM32的OTG_FS外设自带上拉/下拉控制寄存器。但如果你用通用USB PHY,就要外部设计。我贴一个常见的电路结构:

D+ line
  |
  +---[15kΩ]---GND     (Host下拉,通过MOS管控制通断)
  |
  +---[1.5kΩ]---3.3V   (Device上拉,通过MOS管控制通断)
  |
  +---To PHY D+ pin

D- line 同理

控制逻辑很简单:ID为低(Host模式)时,闭合下拉MOS,断开上拉MOS;ID为高(Device模式)时,反之。注意上下拉不能同时导通,否则直接短路。我曾经见过一个板子因为软件Bug,在状态切换时两个MOS同时开了一瞬间,3.3V和GND之间只串了1.5kΩ和15kΩ,电流约200μA虽没烧,但电平被拉到2.5V附近,导致USB枚举失败。修复方法是加了一段死区时间:先关断一组,延时几微秒再开启另一组。

2.5 硬件设计避坑清单

光说不练假把式。我把这些年踩过的坑列出来,当成检查清单,设计时对着看:

  1. ID线不要悬空——即使不用OTG功能,ID引脚也不能浮空,否则杂波会让芯片乱跳。接一个10kΩ上拉到VDD或下拉到GND,取决于你需要的默认角色。
  2. VBUS电容不要太大——Host端供电后,负载电容过大会导致VBUS上升斜率太慢,超出USB规范(<100μs到4.4V)。我一般控制在10μF~22μF。
  3. ESD保护要靠近连接器——TVS管必须紧贴Micro-AB插座引脚,走线长度不超过5mm。远了等于没装。
  4. D+/D-差分布线要等长——长度差控制在5mil以内,同一层走线,包地间距至少3倍线宽。
  5. 电源开关的EN脚要有上拉/下拉——防止上电瞬间GPIO未初始化时开关误开启。

下面是整个OTG硬件信号流的框架图,帮你把各部分关系串起来:

OTG硬件信号连接结构 Micro-AB 连接器 1:VBUS 2:D- 3:D+ 4:ID 5:GND 插入时机械 与电气连接 VBUS供电管理 负载开关+限流 ADC电压检测 过压/欠压保护 ID角色检测 上拉电阻/恒流源 比较器阈值判断 → Host / Device D+/D-阻抗控制 15kΩ下拉 / 1.5kΩ上拉 MOS管动态切换 OTG控制器 / PHY ID中断 → 角色切换 D+/D-检测 → 枚举 VBUS控制 → 供电 中断信号 → CPU 关键信号流:ID → 角色判定 → 上下拉切换 + VBUS切换 → 正常枚举

硬件连接是一切的根基。信号定义搞清楚了,后面驱动加载失败排查时你才能精准锁定问题出在哪个引脚、哪个电平上。下一层咱们直接讲驱动加载的时序流程,但那是后话了。先回去量一量你自己板子上的ID电压,看看是不是对的——我保证你会发现惊喜。