3. PD协议基础概念:VDM、DO、Message类型、GoodCRC机制

好,咱们今天聊点硬核的。PD协议里这几个概念,说白了就是整个通信体系的骨架。你搞懂了它们,后面看协议栈就跟看说明书一样简单。

我个人习惯把PD协议想象成两个人对话。一个人说“我要5V 3A”,另一个人得回一句“收到,没问题”。这个一来一回的过程,就涉及到消息怎么封装、怎么确认、怎么携带额外信息。嗯,咱们一个一个拆开讲。

3.1 VDM – 厂商自己的小算盘

VDM,全称是Vendor Defined Message。翻译过来就是“厂商自定义消息”。

为什么需要这个东西?你想啊,USB-IF组织定义的标准消息只能满足通用需求。但每个芯片厂商都有自己的小算盘——比如我想让我的充电器支持私有快充协议,或者我想在CC线上传输一些调试信息。这时候标准消息就不够用了。

VDM就是留给厂商的“自留地”。它分为两种:

  • Unstructured VDM:没有固定格式,厂商自己定义内容。说白了就是给你一段原始数据通道,你想传什么就传什么。
  • Structured VDM:有固定格式,包含VID(厂商ID)、CMD(命令码)等字段。这种更规范,适合做标准化的扩展功能。

重点来了:Structured VDM里有一个叫“Discover Identity”的命令。我当年调试一个Type-C扩展坞时,就靠这个命令读取了对方芯片的厂商信息和产品版本号。没有VDM,你根本不知道对面接的是什么设备。

我的经验:做私有快充协议时,VDM是绕不开的。我曾经在某个项目里,用Unstructured VDM在CC线上传输了电池包的电压和温度数据。省掉了一根I2C线,老板直呼内行。

3.2 DO – 数据对象,消息的“肉”

DO,Data Object,数据对象。你可以把它理解为消息体里的具体内容。

PD协议里,一条消息由Header和若干个DO组成。Header告诉对方“我这条消息是什么类型”,DO则告诉对方“具体参数是什么”。

举个例子,一条请求电源能力的消息:

Header: 0x2F01  (消息类型=Request, 对象数量=1)
DO[0]:  0x2D0C  (电压=5V, 电流=3A, 无USB通信能力)

你看,Header只占4个字节,真正干活的是后面的DO。DO的格式根据消息类型不同而变化:

  • 电源能力DO:包含电压、电流、供电方向等信息
  • VDM DO:包含VID、CMD、具体数据
  • BIST DO:测试模式用的,平时用不到

注意:DO的字节序是小端模式。我见过不止一个新手工程师,在解析DO时忘了字节序转换,结果读出来的电压值完全不对。嗯,调试了一整天才发现是这个问题。

3.3 Message类型 – 就这几种,别怕

PD协议的消息类型其实不多。我列个表给你看:

消息类型 方向 作用
Source_Capabilities Source → Sink 告诉对方我能提供哪些电压电流
Request Sink → Source 我要这个电压电流组合
Accept Source → Sink 好的,我接受你的请求
PS_RDY Source → Sink 电源已经准备好了,可以用了
VDM 双向 厂商自定义消息
Hard_Reset 双向 出错了,重新来

你想想看,整个PD协议的核心流程,其实就是这几个消息在来回跑。Source发Capabilities,Sink发Request,Source回Accept,然后PS_RDY。就这么简单。

但要注意,每个消息都有严格的时序要求。比如从Accept到PS_RDY,必须在15ms内完成。我曾经在一个项目里,因为电源切换电路响应太慢,导致PS_RDY超时,Sink直接发了Hard_Reset。嗯,那段时间我天天盯着示波器看CC线上的波形。

3.4 GoodCRC – 每个消息都要说“收到”

GoodCRC机制,是PD协议里最容易被忽视但又最重要的部分。

PD协议工作在CC线上,这条线是半双工的。也就是说,同一时刻只能一个人说话。那怎么保证消息没丢呢?答案就是GoodCRC。

每次收到一个消息,接收方必须在1ms内回复一个GoodCRC消息。这个GoodCRC里包含了发送方消息的CRC校验值。发送方收到GoodCRC后,比对一下CRC值对不对。如果对,说明消息完整到达了。如果不对或者超时没收到,发送方就会重发。

关键点:GoodCRC本身也是一个消息,它也需要被确认。但PD协议里有个巧妙设计——GoodCRC不需要再回复GoodCRC。否则就会无限循环下去。你想想看,如果每个GoodCRC都要再回复一个GoodCRC,那CC线上就全是确认消息了,啥正事也干不了。

我刚开始做PD开发时,总觉得GoodCRC是多余的。直到有一次,我在一个长线缆的Type-C项目里,发现CC线上的信号质量很差,消息经常丢包。没有GoodCRC机制,整个通信就乱套了。从那以后,我再也不敢小看这个小小的确认消息。

避坑指南:我曾经在调试时发现,某些便宜的PD芯片在收到消息后,回复GoodCRC的时间超过了1ms。结果发送方认为消息丢了,开始重发。重发又导致接收方收到重复消息,整个状态机就乱了。所以选型时一定要看芯片的GoodCRC响应时间,别光看价格。

3.5 这几个概念怎么串起来?

好,咱们把今天讲的几个概念串起来,看一个完整的例子:

  1. Source发一条Source_Capabilities消息,里面包含两个DO,分别表示5V 3A和9V 2A。
  2. Sink收到后,先回一个GoodCRC,告诉Source“我收到了”。
  3. Sink解析DO,决定要9V 2A,于是发一条Request消息,DO里填上9V 2A的编码。
  4. Source收到Request,回GoodCRC。
  5. Source检查Request是否合法,合法就回Accept消息。
  6. Sink收到Accept,回GoodCRC。
  7. Source切换电源输出到9V,然后发PS_RDY消息。
  8. Sink收到PS_RDY,回GoodCRC。然后开始使用9V电源。

你看,每一步都有GoodCRC在兜底。没有它,整个协议就像没有安全带的过山车——刺激是刺激,但随时可能翻车。

至于VDM,它可以在任何时候插入。比如Source在发Capabilities之前,先发一个VDM问问Sink“你支持我的私有快充协议吗?”如果Sink支持,后面就可以走私有协议了。这就是VDM的灵活之处。

好了,这一章的内容就到这。下一章咱们聊聊PD协议的状态机,那才是真正考验逻辑思维的地方。到时候我会拿一个实际项目的状态机图出来,咱们一行一行地分析。