3. PD 消息类型详解:Control Message、Data Message、Extended Message

好,咱们进入正题。PD 协议里跑的消息,说白了就三大类:控制消息、数据消息、扩展消息。我刚开始啃协议的时候,也被这堆名字搞得头晕。后来发现,你只要抓住一个核心——消息的用途决定了它的分类

打个比方:控制消息就像两个人打招呼的「嗯」、「好的」、「不行」;数据消息就像递过去的一张名片,上面写满了参数;扩展消息呢,就是名片背面再贴一张纸,写点额外信息。嗯,这么一想就清晰多了。

3.1 Control Message(控制消息)

控制消息,长度固定,就 4 个字节。没有数据负载,纯粹用来做握手和状态确认。我做过一个项目,设备老是莫名其妙断开,最后抓包发现是 GoodCRC 没回——说白了就是对方没收到「我收到了」这个确认。

常见的控制消息有这些:

消息类型 作用 个人经验
GoodCRC 确认收到上一条消息 必须回,不回就超时重传
Accept 接受对方的请求 比如接受新的电压电流配置
Reject 拒绝对方的请求 我曾经遇到过因电压不支持而拒接的情况
Wait 让对方等一下 常用于电源正在忙的时候
Soft Reset 软复位,重置协议状态机 别乱发,发完要重新协商
Hard Reset 硬复位,物理层都重置 相当于拔线重插的效果
注意:GoodCRC 是 PD 通信的基石。我曾经调试一个快充协议栈,发现设备每隔几秒就断连,抓包一看,原来是芯片的 CRC 校验逻辑有 bug,导致 GoodCRC 一直没发出去。排查了整整两天,最后发现是硬件中断优先级配错了。

3.2 Data Message(数据消息)

数据消息就复杂多了。它带有数据负载,长度不固定。说白了,就是用来传递具体参数的。

最核心的两个数据消息:

  • Source_Capabilities:源端(比如充电器)告诉设备「我能提供这些电压电流组合」。我习惯把这个消息叫做「菜单」,设备从菜单里选一个。
  • Request:设备端回复「我要这个」。注意,Request 里还包含了电流需求、是否支持 USB 通信等细节。

举个例子:

// 一个典型的 Source_Capabilities 消息内容(简化)
PDO 1: 5V @ 3A   (固定)
PDO 2: 9V @ 2A   (固定)
PDO 3: 15V @ 1.5A (固定)
PDO 4: 3.3V-11V @ 3A (可调)

设备收到后,会根据自己的需求选一个 PDO,然后发 Request。这里有个坑——设备不能选一个源端没提供的电压。我曾经见过一个第三方充电器,固件写错了,PDO 列表里只有 5V,但设备硬要 9V,结果 Reject 满天飞,最后超时断开。

小技巧:调试时,我习惯用逻辑分析仪抓一下 Source_Capabilities 的 PDO 数量。如果设备一直 Reject,先看看是不是 PDO 数量对不上。很多时候,问题出在源端只发了 2 个 PDO,但设备以为有 3 个。

3.3 Extended Message(扩展消息)

扩展消息,是后来 PD 3.0 才引入的。为什么需要它?因为有些信息,比如固件升级、电池状态、制造商信息,用普通数据消息装不下。

扩展消息的特点:

  • 消息头里有个扩展标志位,置 1 就表示这是扩展消息
  • 数据长度可以超过普通消息的限制(最多 260 字节)
  • 常用于 VDM(Vendor Defined Message)固件升级

我记得有一次,客户要求支持通过 PD 协议升级充电器固件。当时我就在想,普通数据消息最多传几十个字节,升级固件动辄几百 KB,怎么搞?答案就是扩展消息。它支持分片传输,一次传不完就分多次。

重点:扩展消息的传输需要双方都支持 PD 3.0。如果有一方是 PD 2.0,扩展消息会被直接忽略。所以,做兼容性测试时,一定要拿 PD 2.0 的设备试试,看看会不会出问题。

3.4 三种消息的协作关系

你想想看,一个完整的 PD 协商过程,这三种消息是怎么配合的?

  1. 源端发 Source_Capabilities(数据消息)—— 告诉设备我能给什么
  2. 设备回 GoodCRC(控制消息)—— 我收到了
  3. 设备分析后,发 Request(数据消息)—— 我要这个
  4. 源端回 GoodCRC(控制消息)—— 收到你的请求
  5. 源端决定接受还是拒绝,发 AcceptReject(控制消息)
  6. 如果接受,源端切换电压,然后发 PS_RDY(控制消息)—— 电压已稳定

你看,控制消息负责握手和确认,数据消息负责传递参数,扩展消息负责补充信息。三者缺一不可。

避坑指南:我曾经在一个项目中,把 GoodCRC 的优先级设得太低,导致数据消息都发完了,GoodCRC 还没发出去。结果对方一直重传,整个通信链路卡死了。后来我把 GoodCRC 的发送优先级提到最高,问题就解决了。记住:GoodCRC 必须优先处理,不能排队等

嗯,这一节的内容就到这里。三种消息类型,说白了就是 PD 通信的三种「语言」:控制消息是短促的命令,数据消息是详细的参数,扩展消息是额外的信息。搞懂了它们,你就掌握了 PD 协议通信的底层逻辑。