供电能力基础概念:电压、电流、功率、Profile 定义

说实话,刚接触 USB PD 的时候,我也觉得电压电流功率嘛,初中物理就学过的东西,有什么好讲的?但真正在项目里调协议栈的时候才发现,PD 里对这几个基础量的定义跟咱们平时想的不太一样,尤其是那个 Profile 的概念,搞不清楚,后面什么 Source Capabilities、Request 消息全都看不懂。这一节咱们就把这些地基打扎实。

电压、电流、功率——在 USB PD 语境下重新理解

USB PD 2.0/3.0 定义了固定的电压档位:5V、9V、15V、20V。为什么是这几个值?我个人的理解是,5V 是传统 USB 的老本行,保证向下兼容;9V 给手机快充用;15V 给平板或笔记本轻度供电;20V 则基本覆盖主流笔记本的需求。电流从 3A 起步,最高到 5A(需要 Emark 线缆支持)。功率就是电压乘以电流,比如 20V / 5A 就是 100W。

但这里有个坑:USB PD 里的电压 不是随便调的。我见过有工程师想当然地认为“既然 PD 能协商,我能不能要一个 12V 输出?” 不行。PD 只认上面那四个固定电压,加上 PPS 模式下的可调电压(但那是另一回事)。你想想看,要是每款设备都自定义一个电压,那充电器不就得做得跟万能充一样了吗?

还有个容易忽略的点:功率是协商出来的上限,不是实际一直跑满。比如你的手机协商了 9V/3A (27W),但实际充电时可能只用了 2A,功率就变成 18W。这一点我在调试日志里经常看到,有些人看到协商功率是 100W,就以为线缆和连接器一直在承受 100W 的热损耗,其实不是的,只有实际负载电流才是真正的应力。

关键记忆口诀:

  • 电压:5V、9V、15V、20V(固定档)
  • 电流:3A / 5A(取决于线缆和连接器能力)
  • 功率:电压 × 电流,单位 W

Profile 是什么?为什么它比“电压电流”更高级?

你可以在你的手机充电器上看到印着“5V/3A, 9V/3A, 15V/3A, 20V/2.25A”之类的字符串。这每一个 “电压/电流” 的组合在 USB PD 协议里就叫做一个 Profile。更准确地说,一个 Profile 是一个 供电能力描述单元,它至少包含电压值和最大电流值。

我举个例子。一个 45W 的充电器,它的 Source Capabilities 消息里会携带 4 个 Profile:

Profile 编号 电压 (V) 最大电流 (A) 最大功率 (W)
1 5 3 15
2 9 3 27
3 15 3 45
4 20 2.25 45

你看,两个不同的 Profile 可以都有 45W 的功率(15V/3A 和 20V/2.25A),但电压和电流组合不同。这就给了 Sink(受电设备)选择的余地——是想要低压大电流,还是高压小电流?这里面就看设备端的充电策略了。

Profile 的数据结构长什么样?

还记得我们上一章(好吧,其实我只是习惯这么说)提到的 USB PD 消息结构吗?一个 Source Capabilities 消息由若干个 Power Data Object(PDO)组成,每个 PDO 就是一个 Profile。在二进制里,它长这样(以 32 位为例):

位域说明(固定电压 PDO):
[31:30] 保留 / 固定供应标志
[29:20] 最大电流(以 10mA 为单位)
[19:10] 电压(以 50mV 为单位)
[9:0]  峰值电流能力等控制位

举个例子:20V / 3A 的 Profile 怎么填?电压 = 20V / 0.05V = 400,电流 = 3A / 0.01A = 300。所以二进制数值大致是 (400 << 10) | 300。我当年第一次对着规格书算这个的时候,还特意用 Python 验证了两遍,就是怕把移位搞反了。

实际编程中,我们通常用宏或者内联函数来打包 PDO,不需要手算每一位。但理解二进制布局能帮你在抓到的 log 里直接识别出错误 Profile。

一张图搞懂供电能力协商核心

下面这个 SVG 画的是从 Source 发起到供电建立的全流程,重点放在 Profile 的定义和使用上。别看它简单,每一次 PD 握手都是这个循环。

Source Capabilities 消息结构与协商流程 USB PD Source (充电器 / 电源适配器) USB PD Sink (手机 / 笔记本等) 1. Source 发送 Capabilities 消息 包含多个 Profile(PDO) Profile 列表示例 5V / 3A 9V / 3A 15V / 3A 20V / 3A 等待 Sink 的 Request 2. Sink 选择一个 Profile 发送 Request 消息 3. Source 发送 Accept / PS_RDY 供电建立! Source 切换到所选 Profile

避坑指南:Profile 的常见误解

我曾经在客户现场遇到一个典型问题:

一台笔记本只支持 20V / 3A(60W)的单一 Profile,但用户给它配了一个 100W(20V / 5A)充电器。两者都能工作在 20V,按理说应该没问题?可是笔记本的适配器检测电路在 Emark 线缆的电流能力上踩了坑——线缆标记支持 5A,但笔记本主板上的电源开关管只能承受 3A。结果就是,当笔记本尝试从 5A 的线缆上获取更多电流时,限流保护被触发,反复重启。

教训:Sink 端必须明确自己支持的电流上限,并且在 Request 消息中请求不超过自身能力的电流值。Profile 里的最大电流是 Source 能提供的上限,不一定是 Sink 能承受的上限。

另一个容易忽略的点:PPS Profile 是纯数字控制的

除了上面说的固定电压 Profile,USB PD 3.0 引入了 PPS(可编程电源) Profile。它的电压和电流可以在一个范围内以 20mV / 50mA 的步进连续调节。比如 3.3V~21V / 3A。这种 Profile 在二进制里的位域定义完全不同,但核心思想一样——它是一个“范围的 Profile”,而不是固定值。我在给手机做快充适配时,就特别喜欢用 PPS,因为它能把充电电压正好压在电池的恒压点上,减少不必要的转换损耗。

如果你只是想快速验证 PD 通信,可以用一个支持 PPS 的电源和一台手机(比如某米系列),在数据线上挂一个 PD 分析仪,你就能看到 Source Capabilities 里有两种类型的 PDO:固定 PDO 和 PPS PDO。

嗯,大概就这么多。供电能力的基础说白了就是搞清楚这几个值怎么打包成 Profile,又是怎么在协商过程中被选择的。你想想看,要是连 5V 和 9V 都记混了,后面看 PD 协议栈的代码那基本就是在看天书。所以别嫌这部分啰嗦,打牢了,后面十几章都是基于这些概念展开的。