4、PD协议进阶:电源规则、PDO详解、APDO介绍与状态机

好,咱们接着往下聊。上一章我们把PD协议的基础握手流程走了一遍,相当于学会了怎么跟充电器“打招呼”。但光打招呼没用,你得知道它能给你多少电,你该要多少电,这里面就涉及一套严格的规矩——也就是电源规则。

我个人习惯把PD协议里的电源管理比作一场谈判。你(设备)和充电器(Source)坐在桌子两边,手里各拿一份菜单。菜单上的菜就是PDO,而谈判的底线就是Power Rules。

4.1 电源规则(Power Rules)——谈判的底线

电源规则说白了就是:你能要多少,不能超过多少。PD协议里规定了几个硬性指标,违反了下场就是协议报错,甚至烧设备。

  • 最大功率限制:单个PDO的功率不能超过100W(标准PD 3.0),后来PD 3.1扩展到了240W(EPR)。
  • 电压电流范围:固定PDO的电压是5V、9V、15V、20V这几个档位,电流则根据线缆和端口能力决定。
  • 功率平衡:你不能同时拉两个PDO的功率,一次只能选一个。

核心要点:电源规则不是建议,是强制要求。我在项目中遇到过有人试图让设备同时请求5V和20V,结果协议直接卡死,充电器拒绝响应。

嗯,这里要注意:Source(供电端)和Sink(受电端)的规则不完全对称。Source负责提供菜单,Sink负责点菜。但Sink不能点菜单上没有的菜,也不能点超过自己能力的菜。

4.2 PDO(Power Data Object)详解——菜单上的菜

PDO就是电源数据对象,它描述了充电器能提供的每一组电压和电流组合。PDO分为两种:固定PDO可变PDO(Battery PDO)。

4.2.1 固定PDO

最常见的类型。比如5V/3A、9V/3A、15V/3A、20V/5A。每个固定PDO包含:

  • 电压值:以50mV为单位编码
  • 电流值:以10mA为单位编码
  • 标志位:比如双角色支持、USB通信能力等

举个例子,一个标准的20V/5A PDO,在二进制里长这样:

// 20V/5A 固定PDO 的32位表示(简化)
Bit 31-20: 电压 = 20.0V / 0.05V = 400 (0x190)
Bit 19-10: 电流 = 5.0A / 0.01A = 500 (0x1F4)
Bit 9-0:  标志位 = 0x000 (无特殊功能)

你想想看,充电器会一次性把所有支持的PDO都发给设备。设备收到后,从中选一个最合适的。我刚开始做PD开发时,总以为PDO越多越好,后来发现有些充电器会发一堆重复的PDO,反而让设备选择困难。

4.2.2 可变PDO(Battery PDO)

这种PDO不固定电压,而是给一个范围。比如“5V到20V,最大3A”。它主要用于电池供电的设备,比如笔记本电池包。说实话,我在实际项目中很少见到可变PDO,大部分设备都用固定PDO。

个人经验:如果你在做Sink设备,建议优先支持固定PDO。可变PDO的兼容性测试比较麻烦,我曾经因为一个可变PDO的电压范围没处理好,导致充电器反复重启。

4.3 APDO(Augmented PDO)介绍——进阶玩法

APDO是PD 3.0引入的新东西,全称是“增强型电源数据对象”。它跟普通PDO最大的区别是:支持可编程电压(PPS,Programmable Power Supply)。

说白了,APDO允许设备在充电过程中动态调整电压,而不是只能选固定的几个档位。比如你可以在5V到20V之间,以20mV为步进,精确调整电压。

APDO的结构跟固定PDO不太一样:

// APDO 的32位表示(PPS模式)
Bit 31-24: 最大电压 = 20.0V / 0.02V = 1000 (0x3E8)
Bit 23-16: 最小电压 = 5.0V / 0.02V = 250 (0xFA)
Bit 15-10: 最大电流 = 5.0A / 0.05A = 100 (0x64)
Bit 9-0:  标志位 = 0x000

为什么要用APDO?举个例子:手机快充。传统PDO只能选9V或12V,但电池在低电量时可能更适合8.5V,高电量时适合11V。APDO就能做到这种精细调节。

避坑指南:我曾经在一个项目中,设备请求了APDO的PPS模式,但充电器实际输出的电压纹波很大,导致设备电源管理芯片过热。后来发现是充电器的PPS实现有bug。所以,使用APDO前一定要做充分的兼容性测试

4.4 PD协议状态机——谈判的流程

PD协议的状态机,就是整个电源协商过程的“剧本”。它规定了每个阶段该做什么,不该做什么。我把它分成几个关键状态:

状态 描述 关键动作
PE_SNK_Startup Sink设备启动,等待Source能力 发送Hard Reset或等待Source Capabilities
PE_SNK_Send_Capabilities Source发送能力包 发送Source Capabilities消息
PE_SNK_Evaluate_Capability Sink评估能力包 选择一个PDO,准备发送Request
PE_SNK_Select_Capability Sink发送请求 发送Request消息,包含选中的PDO索引
PE_SNK_Transition_Sink 等待Source切换电源 接收Accept和PS_RDY消息
PE_SNK_Ready 电源协商完成,正常工作 持续监测电压电流,可发送Soft Reset

你可能会问:状态机这么复杂,实际开发中怎么用?我的建议是:不要自己从头写状态机。市面上有现成的PD协议栈,比如TI的TUSB320、ST的STUSB4500,它们内部已经实现了完整的状态机。你只需要配置参数,然后读取结果就行。

但如果你非要自己写,嗯,那就要注意几个坑:

  • 超时处理:每个状态都有超时时间,比如等待Source Capabilities不能超过500ms。超时了要发Hard Reset。
  • 错误恢复:如果收到不符合预期的消息,要能优雅地回到初始状态,而不是死锁。
  • 状态转换的原子性:从一个状态到另一个状态,中间不能被打断。我曾经因为中断处理不当,导致状态机在Transition阶段卡住,充电器一直不输出电源。

总结一下:电源规则是底线,PDO是菜单,APDO是进阶玩法,状态机是流程。把这四个东西搞明白,PD协议你就掌握了八成。下一章我们聊聊实际硬件设计中的注意事项,比如CC引脚的保护、线缆检测等。

好了,今天就到这里。记住,做PD开发,耐心比技术更重要。调试时多看看协议规范,少走弯路。