VBUS 检测与电源管理
VBUS 这条线,在 USB OTG 里可不只是供电那么简单。它同时承载着角色协商、连接检测、电源预算管理这些任务。一旦 VBUS 出问题,轻则设备不识别,重则烧接口。我这几年处理过的 OTG 异常案例,至少有一半都能追溯到 VBUS 的检测或电源控制上。
4.1 VBUS 电压阈值与检测机制
我习惯把 VBUS 检测分成两个层面:物理层和协议层。物理层关心电压到没到、稳不稳;协议层关心什么时候该切换角色、什么时候该关电源。
4.1.1 标准的电压阈值
USB 2.0 规范里,VBUS 有效范围是 4.75V ~ 5.25V。但实际应用中,OTG 设备需要更精细的阈值判断。下面这张表是我做项目时经常对照的参考值:
| 检测事件 | 阈值范围 | 说明 |
|---|---|---|
| VBUS 有效 (A 设备) | 4.4V ~ 5.5V | A 设备输出有效电压 |
| VBUS 有效 (B 设备) | 3.3V ~ 4.4V | B 设备检测到外部供电 |
| VBUS 掉电阈值 | < 3.0V | 触发掉电保护 |
| 过压保护 | > 5.8V | 立即断开电源开关 |
实际调试时,建议用示波器抓 VBUS 上电波形。我曾经遇到过一批芯片,ADC 采样延迟导致 VBUS 阈值判断慢了 20ms,结果角色切换时 A 设备已经断电,B 设备还在等 ID 中断——死锁了。后来改成了连续三次采样取中值,问题才解决。
4.1.2 检测电路设计要点
你想想看,MCU 的 ADC 引脚通常不能直接接 5V。所以 VBUS 检测必须用分压电阻。我个人习惯用两颗 10kΩ 的电阻分压到 2.5V 左右,这样 ADC 输入范围能充分利用。但要注意分压电阻的精度,1% 和 5% 的差别在阈值判据上可能会差 0.1V,这对 OTG 角色切换来说已经不小了。
另外,VBUS 检测还要考虑 毛刺滤波。实际线缆插拔时,VBUS 会有几十微秒的抖动。我一般在软件里加 2ms 的去抖延时,硬件上在分压节点加一个 0.1μF 的电容。
4.2 电源开关控制策略
VBUS 供电不是一直开着的。OTG 规范要求:作为 A 设备时,必须先检测到 B 设备插入才能开启 VBUS;作为 B 设备时,不能向外供电。
4.2.1 电源开关选型
我常用的电源开关有 TPS2553、RT9715 这类带过流和热关断的芯片。选型时要注意三点:
- 导通电阻:太大会导致 VBUS 压降,USB 规范要求端口压降不超过 125mV(Full Speed 场景更严)。
- 开关速度:从使能到输出稳定的时间,最好小于 1ms。
- 反向阻断:当内部电源关闭时,不能让 VBUS 上的电压倒灌到系统电源。
我曾经在一次平板项目中,选了导通电阻 0.3Ω 的开关,结果全速 USB 设备插上去功率不够。换用 0.05Ω 的 TPS2553 后,压降从 300mV 降到 50mV,问题解决。记住:线缆本身的电阻也要算进去。
4.2.2 使能时序控制
软件控制电源开关时,时序非常重要。我见过一个典型 bug:主控先开启 VBUS,然后才设置 OTG 角色。结果 VBUS 上电瞬间,从设备还没完成初始化,直接识别成了 Host。正确的做法是:
- 检测 ID 引脚,确定设备角色。
- 配置 USB 控制器模式(Host 或 Device)。
- 等待 10ms(让逻辑稳定),再使能电源开关。
下面是一个基于 STM32 的伪代码,展示 VBUS 使能流程:
void otg_vbus_enable(bool enable) {
if (enable) {
// 1. 先配置 OTG 控制器为 Host
USB_OTG_CoreInit(USB_OTG_FS_HOST);
delay_ms(10);
// 2. 再使能电源开关
GPIO_SetBits(GPIOB, GPIO_Pin_5); // VBUS_EN
VBUS_Status = VBUS_ON;
} else {
// 关闭顺序:先断电源,再复位 OTG 模式
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
delay_ms(5);
USB_OTG_CoreInit(USB_OTG_FS_DEVICE);
VBUS_Status = VBUS_OFF;
}
}
4.3 过流保护与故障处理
过流保护是电源管理的最后防线。USB 规范要求每个端口必须有过流检测,一旦电流超过 500mA(或协商后的值),必须在 50μs 内关断 VBUS。
4.3.1 硬件过流检测
电源开关芯片通常自带 FAULT 引脚,当输出过流、短路或过热时,FAULT 拉低。我建议把 FAULT 接到 MCU 的外部中断引脚上,最快响应异常。有些设计图省事,把 FAULT 接到 GPIO 轮询——但轮询周期如果超过 1ms,可能已经烧坏东西了。
| 异常类型 | 典型触发条件 | 推荐处理 |
|---|---|---|
| 过流 | 电流 > 限流值(如 1.5A) | 立即关断 VBUS,记录错误计数器 |
| 短路 | VBUS 对地电阻 < 0.1Ω | 紧急关断,禁止自动重试 |
| 过热 | 芯片结温 > 150°C | 关断并等待温度下降后 |
千万别忽略过流后的恢复策略。我接手过一个项目,过流后 MCU 立刻重新使能 VBUS,结果 50ms 后再次过流,如此反复,把 USB 座子都给烧焦了。后来我加了一个退避算法:第一次过流等待 1 秒重试,第二次 5 秒,第三次直接锁定,需要用户拔出设备才清除。
4.3.2 软件过流处理流程
实际上,硬件过流检测只能保护严重短路。对于慢速过载(比如接了功率超标的充电器),电流慢慢上升,硬件 FAULT 可能不触发,但长时间运行会损伤电源。我习惯在软件里对 VBUS 电流进行 ADC 采样,设定一个软件阈值(比如 400mA),如果连续 5 次采样超过阈值,则软关断。
下面这个流程图总结了 VBUS 检测与电源管理的核心逻辑:
4.4 高频问题与避坑指南
4.4.1 VBUS 电压检测不准
ADC 参考电压漂移是元凶。我记得有一次用内部 Vref 做参考,温度从 25°C 升到 60°C 时 VBUS 检测值漂了 0.3V,导致角色切换失败。后来改成了外部精密基准(比如 REF3033),漂移降到 0.02V。
4.4.2 电源开关唤醒问题
有些低功耗场景下,CPU 进入睡眠模式,电源开关控制引脚被关闭。我曾经遇到一个设备,插上 OTG 线后 VBUS 始终不输出,排查三天才发现是 GPIO 在睡眠模式下被配置成了高阻。后来在睡眠前保持 GPIO 状态,并在 VBUS 中断引脚上设置了唤醒源。
4.4.3 过流保护误触发
尤其是接电容较大的设备(比如充电宝),上电瞬间浪涌电流很大,硬件过流保护可能误触发。我习惯在电源开关后加一个软启动电路,或者选用带可调限流的开关,把启动时的限流值放宽到 1A,平稳后降到 500mA。
顺便提一句,调试 VBUS 问题时,用 USB 测试仪(比如 Power-Z)查看实际电流电压曲线,比用万用表方便多了。你能看到上电瞬间的尖峰、稳定后的纹波,这些细节往往是问题根源。