第二章 OTG硬件连接与信号定义
做OTG驱动调试,第一关不是看代码,而是看板子上的那几个焊盘和电阻。硬件连接错了,驱动再怎么改也白搭。我早年接手一个项目,板子回来怎么都识别不了设备,查了一个礼拜才发现ID引脚的焊盘虚焊了。嗯,那次之后我就养成了习惯——先拿万用表量一遍信号,再碰软件。
2.1 认识OTG连接器
OTG物理层的核心是连接器。现在最常用的是Micro-AB,也有老一点的Mini-AB。别看插座小,里面5个引脚各司其职。我把它总结成一张表,你对照着看:
| 引脚号 | 名称 | 信号方向 | 功能说明 |
|---|---|---|---|
| 1 | VBUS | 双向 | 4.4V~5.25V供电 |
| 2 | D- | 双向 | USB差分数据负 |
| 3 | D+ | 双向 | USB差分数据正 |
| 4 | ID | 输入(对设备) | 角色识别信号 |
| 5 | GND | 电源 | 地回路 |
注意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 硬件设计避坑清单
光说不练假把式。我把这些年踩过的坑列出来,当成检查清单,设计时对着看:
- ID线不要悬空——即使不用OTG功能,ID引脚也不能浮空,否则杂波会让芯片乱跳。接一个10kΩ上拉到VDD或下拉到GND,取决于你需要的默认角色。
- VBUS电容不要太大——Host端供电后,负载电容过大会导致VBUS上升斜率太慢,超出USB规范(<100μs到4.4V)。我一般控制在10μF~22μF。
- ESD保护要靠近连接器——TVS管必须紧贴Micro-AB插座引脚,走线长度不超过5mm。远了等于没装。
- D+/D-差分布线要等长——长度差控制在5mil以内,同一层走线,包地间距至少3倍线宽。
- 电源开关的EN脚要有上拉/下拉——防止上电瞬间GPIO未初始化时开关误开启。
下面是整个OTG硬件信号流的框架图,帮你把各部分关系串起来:
硬件连接是一切的根基。信号定义搞清楚了,后面驱动加载失败排查时你才能精准锁定问题出在哪个引脚、哪个电平上。下一层咱们直接讲驱动加载的时序流程,但那是后话了。先回去量一量你自己板子上的ID电压,看看是不是对的——我保证你会发现惊喜。