第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 负责在最小~最大电压区间内调整输出,只要保证输出功率不超过广播值即可。这会比固定电流灵活得多。

三种 PDO 字段结构对比 Fixed PDO Variable PDO Battery PDO B31..28: 峰值电流 (3b) B27..20: 电压 (8b) B19..10: 电流 (10b) B9: FR Swap B8: DRP B7: Suspend B6: Uncnst Pwr B5: USB Comm B4..0: Reserved B30..20: 最小电压 (11b) B19..9: 最大电压 (11b) B8..0: 最大电流 (9b) (无控制位) (无 Reserved) B30..20: 最大电压 (11b) B19..9: 最小电压 (11b) B8..0: 最大功率 (9b) (无电流字段) (单位 250mW) 记住:Fixed 有控制位,Variable 和 Battery 没有 Battery 用功率字段代替电流字段,用于电池充电场景

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 代码了——你自己先看看数据结构,会有帮助。