第4章 Source Capabilities 消息的字段解析:Fixed PDO, Variable PDO, Battery PDO
上一章我们把 Source Capabilities 消息的帧结构拆了个底朝天。今天咱们进入正题:里面那三种 PDO(Power Data Object)——Fixed PDO、Variable PDO、Battery PDO。说白了,它们就是电源能提供哪些电压电流档位的「价目表」。我刚开始啃 PD 协议时,老把这三类搞混,后来硬是拿逻辑分析仪抓了一整天波形才彻底理清。嗯,现在用一张表就能说明白。
4.1 Fixed PDO —— 最常见的「固定电压」
Fixed PDO 在所有 Source 消息里几乎都会出现。它代表一个固定的输出电压(5V、9V、15V、20V 等等),外加若干控制位。你想想看,USB PD 最常用的几个电压档——手机快充 9V、笔记本 20V,都是通过 Fixed PDO 广播的。
字段结构(31位数据,去掉预留位后):
| 位段 | 宽度 | 含义 | 我的备注 |
|---|---|---|---|
| 30:28 | 3 bits | 峰值电流能力(未使用,当前保留) | 协议栈里一般直接填 0 |
| 27:20 | 8 bits | 电压 (50mV/LSB) | 比如 5V = 100,9V = 180 |
| 19:10 | 10 bits | 电流 (10mA/LSB) | 3A = 300;芯片内部限流 |
| 9 | 1 bit | Fast Role Swap | 告诉 Sink 我能快速切换方向 |
| 8 | 1 bit | Dual Role Power | 支持 DRP |
| 7 | 1 bit | USB Suspend | 是否允许挂起 |
| 6 | 1 bit | Unconstrained Power | 无限制供电 |
| 5 | 1 bit | USB Communications | 支持 USB 数据通信 |
| 4:0 | 5 bits | Reserved | 始终为 0 |
避坑指南:我曾经在量产项目里遇到 Sink 端不认 9V 档位,反复查才发现 Fixed PDO 的电压值算错了——50mV 精度一位是 100,不是 10。你算电压时别忘了乘以 0.05。
4.2 Variable PDO —— 可调电压的「万金油」
Variable PDO 跟 Fixed 最大的区别是:它能提供一个电压范围,而不是单一电压。我记得第一次做车充项目时,客户要求输出 3.3V~21V 可调,USB PD 协议里靠的就是 Variable PDO 广播这个范围。
字段结构:
| 位段 | 宽度 | 含义 | 典型值 |
|---|---|---|---|
| 30:20 | 11 bits | 最小电压 (50mV/ LSB) | 3.3V → 66 |
| 19:9 | 11 bits | 最大电压 (50mV/ LSB) | 21V → 420 |
| 8:0 | 9 bits | 最大电流 (10mA/ LSB) | 3A → 300 |
为什么电流只有 9 位?因为 Variable PDO 强调电压调节灵活性,电流精度不用太高,最大 5.1A 就已经够用(9 位最大 511,对应 5.11A)。
注意:Variable PDO 不支持控制位(如 FR Swap、DRP)。你如果要同时提供可调电压和控制位,得额外加一个 Fixed PDO 配合使用。我曾经踩过这个坑:只发了一个 Variable PDO,结果 Sink 端认为 Source 不支持角色交换,导致 DRP 协商失败。
4.3 Battery PDO —— 专为电池包设计
Battery PDO 大概是三种 PDO 里最冷门的一种。它专门用来给设备内的电池包充电——比如电动工具、无人机、笔记本的内置电池。你可以把它理解成一套「充电曲线」模板。
字段结构:
| 位段 | 宽度 | 含义 | 备注 |
|---|---|---|---|
| 30:20 | 11 bits | 最大电压 (50mV/ LSB) | 电池满充电压 |
| 19:9 | 11 bits | 最小电压 (50mV/ LSB) | 电池截止电压 |
| 8:0 | 9 bits | 最大功率 (250mW/ LSB) | 单位是瓦,不是电流 |
最大功率的单位是 250mW,比 Fixed 和 Variable 的电流粒度粗。因为电池充电更看重功率约束,而不是电流精确到 10mA。我去年给一款两轮电动车做快充方案,Source 端就广播了一个 Battery PDO:电压范围 36V~42V,最大功率 60W,Sink 端是 BMS 直接解析。
关键区别:Battery PDO 的电流字段被替换成了功率字段。当 Sink 选择 Battery PDO 时,Source 负责在最小~最大电压区间内调整输出,只要保证输出功率不超过广播值即可。这会比固定电流灵活得多。
4.4 三种 PDO 的实用选择策略
写固件的时候到底该用哪种?我一般遵循下面几条原则:
- 固定档位充电/供电 → 用 Fixed PDO。比如 5V/3A、9V/2A、20V/3.25A。90% 的消费电子都在这条路上。
- 需要电压范围适配不同电池 → 用 Variable PDO。做车充、户外电源这类产品时特别有用。
- 客户明确要求电池充电曲线 → 用 Battery PDO。说白了,BMS 知道电池的充电窗口,你只报最大功率就行。
三种 PDO 可以同时出现在一条 Source Capabilities 消息里。USB PD 规范允许最多 7 个 PDO,你可以混搭。我记得做一款 65W 适配器时,就用了 2 个 Fixed(5V/3A、20V/3.25A)加 1 个 Battery(14.8V~16.8V/65W)——给相机电池充电用的。
4.5 避坑总结
- Fixed PDO 的电压和电流单位千万别搞反(50mV 和 10mA)。
- Variable 和 Battery 没有 Dual Role 等控制位,需要角色交换请额外配一个 Fixed PDO。
- Battery PDO 的功率单位是 250mW,不是 10mW,算差一位就是几十瓦的偏差——我曾经因此让充电器过热保护过。
- 记得在协议栈里预留 Fixed PDO 的 B9 (FR Swap) 位,否则部分 Sink 会拒绝协商 20V 档位。
好,这一章就到这。下节课咱们就要手写一段解析 Source Capabilities 的 Python 代码了——你自己先看看数据结构,会有帮助。