第2章 Source Capabilities消息的作用:在PD通信中的位置和意义

2.1 消息概述:什么是Source Capabilities

Source Capabilities消息,说白了就是供电方向受电方递出的一张「能力名片」。它告诉Sink端:我能给你提供哪些电压和电流组合。

这张名片在PD通信中非常关键——它是整个协商过程的起点。没有它,后面的讨价还价根本无从谈起。

我记得刚开始做PD项目时,有一次把Source Capabilities里的PDO顺序搞反了,结果Sink端怎么都不肯进入供电模式。折腾了大半天,最后发现是PDO排序问题。从那以后,我对这条消息就格外上心了。

从消息结构上看,Source Capabilities由两部分组成:

  • 消息头(Message Header):标识消息类型、数据对象个数等信息
  • 数据对象列表(PDO List):实际的能力宣告内容,每条4字节

PDO又分几种不同类型,这里我用一个表格来对比:

PDO类型 能力描述 典型应用场景
固定电源PDO 固定电压 + 最大电流 5V/9V/15V/20V等标准档位
可变电源PDO 电压范围 + 最大电流 宽压适配器,如9V–15V
电池电源PDO 电压范围 + 最大功率 电池包供电场景
可编程电源APDO 可精细调节电压/电流 PD 3.0 PPS快充

你想想看,Sink端拿到这份列表后,才能从中挑选最合适的一组参数来发起请求。所以Source Capabilities的质量,直接决定了后续协商的成败。

2.2 在PD协议栈中的位置

PD协议栈分为三层:物理层、协议层和策略引擎。Source Capabilities消息处于中间层——协议层(Protocol Layer)。

为啥它被放在协议层?因为这一层负责消息的组织、发送和接收。物理层只关心比特流的传输,策略引擎只关心决策逻辑。Source Capabilities既不是纯粹的比特流,也不是上层的策略决策,它恰恰是「组装好的能力数据」,所以协议层是它最自然的位置。

我的一个亲身经历:有次调试一个65W的笔记本适配器,Sink端始终无法识别Source端的能力。抓波形看了半天,发现物理层通信是正常的,策略引擎也没问题。最后定位到协议层的消息头中对象计数字段填错了——少写了一个PDO。你看,协议层的问题,往往最隐蔽。

从依赖关系上看:

  • 协议层依赖物理层提供的数据收发能力
  • 策略引擎依赖协议层传递的消息内容来做决策
  • Source Capabilities消息就是连接物理层和策略引擎的「数据桥梁」

核心理解: Source Capabilities在协议栈中扮演「承上启下」的角色。它把Source端的硬件能力,翻译成策略引擎可以理解的标准化消息。

2.3 在通信流程中的角色

整个PD通信的流程,其实就像一次商务谈判。Source Capabilities就是谈判桌上的「第一份提案」。

标准流程如下:

  1. Source上电,检测到CC线上有设备接入
  2. 发送Source Capabilities,宣告自身能力
  3. Sink解析PDO列表,选择一个最合适的档位
  4. Sink发送Request消息,指明要哪一组电压电流
  5. Source回应Accept,表示同意
  6. Source发送PS_RDY,通知Sink供电已准备就绪
  7. 进入供电阶段

这里有个细节:为什么Source Capabilities必须是第一条消息?原因很简单——Sink在没收到能力宣告之前,根本不知道该请求什么。你想想看,Sink连Source能输出多少V都不知道,怎么开口要?

我在项目中遇到过一种情况:Source端因为某种原因,重复发送了两次Source Capabilities消息。Sink端收到第二条时,会认为Source的能力发生了变化,于是重新启动协商流程。这个行为本身是符合规范的,但如果设计不当,可能导致供电中断。嗯,这里要注意。

Source Capabilities 在 PD 通信中的位置与作用 ① 在 PD 协议栈中的位置 策略引擎 (Policy Engine) 协议层 — Source Capabilities 物理层 (Physical Layer) ← Source Capabilities 所在层级 ② 在通信流程中的作用 Source Source Capabilities Sink Request Accept PS_RDY → 供电 对应关系 Source Capabilities 是 PD 通信的「起点」和「能力边界」 Sink 只能在此边界内请求,超出则协商失败

2.4 消息的实质意义

Source Capabilities消息的意义,绝不仅仅是「报一下电压电流」那么简单。在PD通信中,它承担着三重角色:

  • 能力边界:它划定了Sink可以请求的范围。Sink不能超出这个边界,否则Source会拒绝
  • 协商起点:它是整个PD协商流程的触发信号。没有它,就没有后续的Request、Accept、PS_RDY
  • 安全护栏:Source端通过PDO列表告诉Sink「我只能给你这些」。这防止了Sink提出危险请求

我记得有一次评审设计文档,有人问:为啥不让Sink直接猜Source能输出多少?答案是:猜错了怎么办?如果Sink猜了一个高于Source能力的电压,轻则触发过压保护,重则烧毁Source端的输出级。Source Capabilities的存在,就是为了消除这种不确定性。

我个人习惯在解析Source Capabilities时,先校验PDO的数量和类型,再逐个提取电压电流值。这样做的好处是能尽早发现异常PDO,避免把错误数据传给策略引擎。

解析小技巧: 接收Source Capabilities后,不要急着选第一个PDO。先遍历所有PDO,挑出最匹配当前负载需求的组合。我通常会优先考虑固定电源PDO,因为它们输出的纹波性能最好。

2.5 实践经验与避坑指南

说了这么多理论,来点实际的。这些年做PD项目,我在Source Capabilities这条消息上踩过不少坑,分享几个典型的:

⚠️ 曾经踩过的坑之一:PDO顺序违规

我曾经在Source端按随机顺序排列PDO,结果Sink端解析时跳过了低电压档位,直接请求了高电压。虽然没出事故,但违反了PD规范中「PDO应按照电压从低到高排列」的要求。后来我养成了一个习惯:所有PDO列表在发送前,强制按电压升序排序。

⚠️ 曾经踩过的坑之二:APDO的Delta值填错

有一次做PPS充电器,APDO里的电压步进值(Delta)写错了一位小数。结果Sink端请求的电压总是和实际输出偏差几百毫伏。查了三天,最后发现是规格书里的单位看错了——Delta的单位是20mV,不是10mV。从那以后,我解析APDO时都会用Python写一段校验脚本,自动核对Delta的合理性。

建议: 如果你正在设计Sink端,收到Source Capabilities后最好做一次完整校验。不要假设所有Source端的实现都100%符合规范。我见过不少设备在PDO里填了「不可能」的电压值,比如5000V——显然是个笔误。Sink端要做的是:容错、校验、安全降级。

我建议大家在调试PD通信时,优先抓取Source Capabilities消息的日志。只要这条消息解析正确,后面90%的问题都能定位。如果这条消息本身就有问题,那后面的所有行为都会跟着跑偏。嗯,你想想看,起点错了,后面怎么可能对?

最后说一句:Source Capabilities消息虽然基础,但它在整个PD通信中的地位,就像地基之于高楼。地基没打好,后面再努力也是白搭。