news 2026/9/28 1:25:55

CH224芯片详解:USB PD协议Source Capabilities与IIC数据解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CH224芯片详解:USB PD协议Source Capabilities与IIC数据解析

做嵌入式这几年,只要跟Type-C充电打过交道的人,基本都绕不开CH224这颗芯片。它的定位很明确:一颗PD诱骗/取电芯片,接在设备端充当Sink,让设备可以从PD充电器里拉到5V、9V、12V、20V甚至PPS可调电压。今天我想聊的不是怎么搭电路让它输出固定电压,而是把数据链路彻底翻一遍——从充电器发出来的Source Capabilities报文,到CH224A/Q通过IIC接口暴露给MCU的数据,中间到底发生了什么。

这篇文章适合三类人:一是正在用CH224A/Q做Type-C取电项目、但只停留在“照着参考电路抄”的工程师;二是想用IIC动态切换PD档位、却搞不清寄存器里那些十六进制数据含义的开发者;三是单纯想搞懂USB PD协议里Source Capabilities报文结构、但又不想啃几百页英文规范的朋友。看完之后,你至少能回答三个问题:寄存器里的PDO数据怎么解读?IIC读回来的字节和CC线上跑的报文什么关系?请求电压不生效时该往哪个方向排查?

1. 先搞清楚:Source Capabilities报文到底在说什么

1.1 PD会话里的“Source”和“Sink”分别扮演什么角色

USB PD协议把连接双方分成两个角色:Source是供电端,也就是充电器、电源适配器;Sink是受电端,也就是你的设备、你的板子。CH224A/Q在整条链路里就是标准Sink。

这里有个很常见的误解:很多人以为插上CC线,充电器就直接把20V送出来了。实际上完全不是这样。USB PD所有功率协商都是“请求-应答”模式,充电器默认只输出一个基准电压(通常是5V),然后通过CC线广播自己能提供哪些电压和电流档位,等Sink端选一个档位发回Request,Source确认后才会真正把VBUS电压切换过去。

Source Capabilities这个报文,就是Source端用来“自我推销”的。它会告诉Sink:我有几个档位,每个档位能输出多少伏、多少安,是固定电压还是可编程PPS,电流支持能力是多少。这个过程发生在PD物理连接建立之后、Sink发Request之前。可以理解为双方握手后,供电方向受电方递过来一张菜单,上面列着所有可点的菜和价格。

1.2 Source Capabilities报文的外壳:SOP、Message Header和Data Object

USB PD报文不是纯裸数据,它有完整的“信封”结构。抓包工具或者逻辑分析仪在CC线上看到的物理帧大概长这样:前导码、SOP标志、Message Header、Data Object数组、CRC32。对开发者来说,真正需要关心的是中间三个部分。

SOP是用来标识“这条报文是Source发给Sink的”还是“Sink发给Source的”。SOP表示Source到Sink方向,SOP'表示Sink到Source方向。所以Source Capabilities报文带的是SOP,而CH224回过去的Request、GoodCRC等带的是SOP'。以前有人抓报文时发现方向怪异,多半是没理解SOP和SOP'的差别。

Message Header是16bit的报文头,内容包含Message Type、Message ID、Number of Data Objects(NDO)等信息。Message Type告诉接收方这是一条什么报文,比如GoodCRC、Request、Source Capabilities。NDO直接决定这条报文后面跟了几个Data Object,也就是几个PDO功率描述符。

Data Object才是真正有含金量的部分。每个Data Object固定32bit,对应一个功率档位。Source Capabilities理论上最多可以带7个PDO,所以报文长度是可变的。NDO等于几,后面就有几个32bit的PDO数据。CH224A/Q内部拿到这些PDO之后,会按顺序解析并存储,然后通过IIC寄存器暴露给外部MCU。

1.3 手动解码一个真实的固定PDO

拿最常见的固定电压PDO来举例。一个标准Fixed Supply PDO长这样:

  • bits[31:30] = 00b,表示固定电压档
  • bits[29:24] = 各种能力标志位,比如是否支持双角色、是否支持USB通信、是否支持无约束供电
  • bits[23:20] = 保留位或扩展标志
  • bits[19:10] = 输出电压值,单位50mV
  • bits[9:0] = 最大输出电流,单位10mA

打个比方,如果某个PDO原始值是0x0401912C,怎么拆?先看bits[31:30]是00,确认是固定PDO。电压字段取bits[19:10],数值是0x064,换算一下:100乘以50mV等于5V。电流字段取低10位,0x12C等于300,乘以10mA等于3A。所以这个PDO就是5V/3A档。

再举一个实际充电器常见的组合。某充电器的Source Capabilities报文里带了四个PDO:

PDO序号原始值(十六进制)电压电流
PDO10x0401912C5V3A
PDO20x0402D12C9V3A
PDO30x0403C12C12V3A
PDO40x0406412C20V3A

看到0x640、0x2D0、0x3C0、0x640这些电压字段,对应的就是100、180、240、400这串十进制数,乘以50mV就得到5V、9V、12V、20V。这套换算关系最好刻在脑子里,因为IIC寄存器读回来的原始值完全就是这套格式,只是字节序可能不同。

2. CH224A/Q在这条链路里干了什么

2.1 一颗Sink诱骗芯片的定位

CH224A/Q本质上是一个完整的USB PD Sink控制器。它内部集成了物理层收发器、BMC编解码、协议状态机,以及PDO解析和Request生成逻辑。外部MCU不需要参与PD报文级的交互,只需要通过IIC或者电阻配置告诉芯片“我要哪个档位”,芯片自己就能完成从接收Source Capabilities到发出Request的一整套协议流程。

我最初用这颗芯片的时候有个误区:以为它像一颗普通IIC外设一样,MCU写寄存器就能直接控制VBUS。实际上它的工作模式是“协议处理后映射寄存器”。充电器发来Source Capabilities报文,CH224内部协议引擎先把报文解析成PDO列表,存进内部RAM,再把关键信息映射到IIC寄存器空间。MCU通过IIC去读这些寄存器时,本质上是读芯片已经解析好的“结果”。

所以搞懂Source Capabilities报文结构,跟搞懂CH224A/Q的IIC寄存器,其实是一件事的两面。不懂报文结构,你读回0x0401912C只会一脸懵;懂报文结构,你看到这个值就知道当前充电器在5V/3A档上。

2.2 IIC模式怎么把“报文”变成“寄存器”

CH224A/Q在IIC模式下,芯片作为IIC从机,外部MCU作为主机。芯片会把当前连接状态、PDO数量、每个PDO的原始值、当前请求电压电流、芯片版本等信息映射到一段连续的寄存器地址上。

实际使用中,寄存器空间大致包含这几类:

  • 状态类寄存器:当前是否已建立PD通信、是否已获取Source Capabilities、当前VBUS电压状态等
  • PDO信息寄存器:PDO数量、每个PDO的完整32bit原始值
  • 配置寄存器:目标PDO序号、目标电压、目标电流等
  • 只读信息寄存器:芯片版本号等

需要特别提醒的是,不同批次、不同型号的CH224,寄存器偏移地址可能有差异。网上流传的寄存器表不一定适用于你手上的版本,拿到芯片后第一件事就是对着最新数据手册核对寄存器地址,这一步能省掉后面一大半排查时间。

IIC读回的数据格式一般是小端模式,也就是低字节在前。比如某个PDO的32bit值是0x0401912C,读回来四个字节可能是2C、91、01、04。如果你按大端方式拼,解析结果就完全错乱了。后面我会给一段解析代码,重点就是处理这个字节序问题。

2.3 为什么要用IIC,而不是硬件电阻

CH224系列早期很多型号是纯电阻配置,通过CFG引脚接不同阻值来固定请求某个档位。这种方式的优点是简单、不需要MCU参与,上电即用。缺点也很明显:档位是写死的,想要切换电压必须改硬件电阻。

IIC配置模式的价值在于“动态”。你可以让MCU在运行时读取充电器实际支持的PDO,再根据当前任务动态选择档位。比如同一块板子,待机时用5V低功耗,工作时请求20V跑电机,全部可以由软件控制。甚至可以做自动协商:读回所有PDO之后,找最大电压或者最大功率的档位自动请求,不需要人工干预。

另一个使用IIC模式的好处是调试方便。通过IIC寄存器可以读到芯片当前协商状态,判断问题出在PD通信上还是配置上。纯电阻模式下你只能靠万用表量VBUS,排查手段非常有限。

3. 实操:用IIC把Source Capabilities读出来并解析

3.1 硬件连接与IIC基础

先把最小系统讲清楚。CH224A/Q与MCU之间的IIC接口就两根线:SCL和SDA。这两根线必须接上拉电阻,阻值怎么选是有讲究的。IIC总线是开漏结构,上拉电阻太小会增大灌电流,太大则上升沿变慢。我实测下来,3.3V系统、总线长度在10cm以内、只有一两个从机时,4.7k上拉是稳妥选择;如果走线较长或者挂载设备多,建议降到2.2k到3.3k。超过20cm的飞线,优先用2.2k,否则高速模式下可能直接通信失败。

硬件连接注意事项:

  • SCL、SDA引线尽量短,避免和VBUS、CC线平行走线
  • 上拉电阻的上端接芯片IIC引脚的参考电压,通常是3.3V,不要接5V
  • CH224A/Q的CC1、CC2接Type-C母座的对应引脚,注意不要接反
  • VBUS输出端建议预留一个100uF以上的电解电容,PD协商过程中电压切换会产生瞬间跌落

3.2 寄存器读取流程与代码框架

IIC读取的流程说穿了并不复杂:先读状态寄存器确认PD通信已经建立,再读PDO数量寄存器,然后按PDO数量依次读取每个PDO的四个字节,最后按位解析。我通常会把这段逻辑封装成独立模块,方便后续工程复用。

下面的代码是典型读取流程,寄存器地址以数据手册为准,示例中用了宏定义方便修改。

// 伪代码框架:具体寄存器地址以CH224A/Q数据手册为准 #define CH224_I2C_ADDR 0x5E // 7位从机地址,实际以手册为准 #define REG_DEV_STATE 0x01 // 设备状态寄存器 #define REG_PDO_NUM 0x02 // PDO数量寄存器 #define REG_PDO_BASE 0x10 // PDO数据起始寄存器 uint32_t pdo[7]; uint8_t pdo_count = 0; uint8_t buf[4]; // 1. 读取状态,确认已经连上PD Source uint8_t state = i2c_read_reg(CH224_I2C_ADDR, REG_DEV_STATE); if ((state & 0x01) == 0) { printf("PD Source not detected\n"); return; } // 2. 读取PDO数量 pdo_count = i2c_read_reg(CH224_I2C_ADDR, REG_PDO_NUM) & 0x07; // 3. 循环读取每个PDO的4字节原始值 for (uint8_t i = 0; i < pdo_count; i++) { i2c_read_bytes(CH224_I2C_ADDR, REG_PDO_BASE + i * 4, buf, 4); // 小端拼接 pdo[i] = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24); }

这段代码有几个关键细节。第一个是状态寄存器的位定义,不同版本芯片可能不同,但通常最低位表示“是否检测到PD Source并完成首次握手”。第二个是PDO数量寄存器,实际有效位只有低3位,高5位可能是其他状态,所以要用0x07掩码过滤。第三个是字节序,我在代码注释里已经明确标注小端拼接,如果你发现解析出来的电压数值明显不对,优先检查这一块。

3.3 解析PDO的C代码示例

拿到PDO原始值之后,解析逻辑就很直白了。我按PD规范写了一个解析函数,能识别固定电压PDO和PPS/APDO,并打印出关键信息。

void parse_pdo(uint32_t pdo) { uint8_t pdo_type = (pdo >> 30) & 0x03; if (pdo_type == 0x00) { // Fixed Supply PDO uint16_t voltage_raw = (pdo >> 10) & 0x3FF; uint16_t current_raw = pdo & 0x3FF; float voltage = voltage_raw * 0.05f; float current = current_raw * 0.01f; printf("Fixed PDO: %.1fV / %.2fA\n", voltage, current); } else if (pdo_type == 0x03) { // APDO,常见的是PPS档位 printf("PPS/APDO detected: 0x%08X\n", pdo); } else { printf("Other PDO type: 0x%08X\n", pdo); } }

PPS档位解析起来比固定PDO复杂一些,因为它的电压是一个范围而不是固定值,字段包含最大电压、最小电压、最大电流,单位也不同。如果你只是做诱骗固定电压档位,可以先不处理PPS PDO,按顺序跳过即可。但如果你的充电器是纯PPS输出,那就必须完整解析APDO结构才能正确请求电压。

解析结果打印出来之后,你就能看到类似这样的输出:

Fixed PDO: 5.0V / 3.00A Fixed PDO: 9.0V / 3.00A Fixed PDO: 12.0V / 3.00A Fixed PDO: 20.0V / 3.00A

看到这串输出,说明IIC链路已经打通,CH224收到的Source Capabilities报文也成功解析出来了。到了这一步,“从IIC数据到快充协议”这条路就走通了一半。

4. 实测波形与报文比对

4.1 用逻辑分析仪抓IIC上的数据

IIC调试最有效的工具就是逻辑分析仪。把SCL和SDA接到逻辑分析仪上,采样率建议设到2MHz以上,然后跑一遍读寄存器流程,就能看到完整的IIC波形。

我习惯先抓一次纯读操作来验证基础通信。正常读操作波形应该是:主机发START,然后发从机地址加写位,收到ACK,再发寄存器地址,收到ACK,然后重启IIC总线,发从机地址加读位,接着读回数据。如果波形在地址阶段就出现NACK,那基本可以断定地址写错了或者芯片没进入IIC模式。

抓到的字节序列要和代码里读到的值做交叉验证。比如读PDO数量时,如果逻辑分析仪上显示读回0x04,那说明充电器发了4个PDO,后面循环读16个字节也是对的。如果数量对但PDO值解析出来不合理,就要检查是不是IIC时钟太快导致数据错位。

IIC通信速度也要注意。很多MCU默认硬件IIC是400kHz快速模式,但某些CH224A/Q的IIC接口对时序要求偏保守,实测400kHz在某些飞线环境下会出现偶发错误。我一般先用100kHz标准模式把功能跑通,确认无误后再尝试提升速度。

4.2 用CC分析仪抓PD报文的典型时序

IIC抓的是芯片和MCU之间的“内部数据”,但真正能验证完整链路的是抓CC线上的PD报文。市面上有专门的USB PD分析仪,比如带PD抓包功能的Type-C协议分析仪,可以解析出完整的报文交互过程。

典型场景下,你会看到这样的时序:

  1. Source先发Source Capabilities报文,里面带4个PDO
  2. Sink(也就是CH224)回一个GoodCRC确认收到
  3. Sink发Request报文,指定要向第几个PDO请求电压和电流
  4. Source回Accept确认可以执行
  5. Source回PS_RDY,表示VBUS电压已经稳定到目标值

我之前调试时遇到过一个有意思的现象:CH224请求20V档位,但实测VBUS只有5V。抓CC报文发现Request报文里Object Position填的是3,对应12V档,不是20V档。为什么会这样?查下来发现是PDO排序问题,充电器的20V档在PDO5的位置,而我在配置寄存器里填的是“第3档”,没有先读PDO列表确认顺序。

4.3 两类数据如何对应起来

把IIC读到的寄存器和CC线上的报文放在一起对照,整个链路就非常清晰了。

比如PD分析仪显示Source Capabilities报文有四个PDO,原始值分别是0x0401912C、0x0402D12C、0x0403C12C、0x0406412C,那么IIC读回来的PDO数量寄存器应该是4,四个PDO寄存器组的拼值应该和上面完全一致。如果PD分析仪显示有PPS档位,而IIC读回来的PDO数量比分析仪报文里的Data Object数量少,那要注意是不是芯片固件版本不支持PPS解析,需要看芯片手册确认。

调试对象工具关键信息对应关系
PD物理层逻辑分析仪/PD分析仪SOP、Message Header、PDO数组协议原始的“信”
PD协议层PD分析仪Source Capabilities、Request、PS_RDY状态双方交互过程
芯片内部IIC逻辑分析仪状态寄存器、PDO数量、PDO原始值芯片解析后的“结果”

我强烈建议至少抓一次PD分析仪的完整报文,哪怕只看一次都好。因为只有看到报文层面的完整流程,你才会真正理解CH224A/Q在为你处理多少复杂的协议工作——那些BMC编解码、CRC校验、状态机跳转,全被它一颗芯片消化掉了。

5. 常见问题与排查技巧实录

5.1 IIC读不到数据或读到0xFF

这是最常遇到的问题,基本可以按三个方向排查。

第一个方向是地址错了。CH224A/Q的IIC从机地址在网上有多个版本流传,有人说0x5E,有人说0x7F,还有人说0x54。我在不同批次芯片上确实遇到过地址不一致的情况,最可靠的办法是看芯片丝印和最新数据手册,不要拿网上的老代码直接抄。如果你用的是一个错误地址,回读数据大概率是0xFF或者干脆NACK。

第二个方向是芯片没有进入IIC配置模式。CH224A/Q可能有多种配置方式共存,封装上通常有模式选择引脚或者通过外部电阻决定配置模式。如果芯片工作在电阻模式而非IIC模式,SCL和SDA可能不会响应通信。排查方法是检查模式配置引脚的电平是否和数据手册要求一致。

第三个方向是上电时序问题。PD协商需要一个过程,芯片从插入到拿到Source Capabilities报文需要几百毫秒。如果MCU上电后立刻就去读IIC寄存器,此时PD协商还没完成,状态寄存器显示未就绪,PDO数量可能是0。建议MCU启动后延时几百毫秒再开始读,或者做重试机制。

5.2 请求高电压不生效

明明读到了20V的PDO,配置也写了要20V,但VBUS就是出不来20V,这个问题要分几层看。

第一层,确认你的Request报文里的电流值没有超过PDO的电流能力。很多充电器的20V档只是“标称”支持,实际电流能力可能只有2A甚至1.5A。RDO里面Operating Current和Max Operating Current都是10mA单位,如果填的电流超过PDO最大值,Source可能会Reject请求,甚至直接不给升压。

第二层,有些Source对多档位跳变有限制。直接从5V跳到20V可能失败,但先请求中间档位再跳就能成功。我遇到过某些充电器必须按PDO序号顺序升压,跳档请求会被拒绝。针对这种充电器,可以做一个渐进请求策略:先请求第二档,稳定后再请求目标档。

第三层,检查是否请求到了PPS档位。PPS档位的Request格式和固定PDO不一样,需要填目标电压和电流,而不是填PDO序号。如果你把PPS PDO当成固定PDO来请求,配置可能完全不生效。

5.3 新手最容易忽略的坑

第一个坑是PDO序号和电压值搞混。很多人以为“第4档”就是20V,其实PDO序号是充电器自己定义的,顺序没有统一标准。有的充电器把5V、9V、PPS放前面,20V放最后;有的充电器把所有固定电压放完才放PPS。正确做法永远是先读PDO列表,再从列表里找目标电压对应的序号,绝不要凭经验硬编码。

第二个坑是电流配置存的是A还是mA。CH224相关例程里,电流寄存器有两种单位混用的情况,有的需要写实际安培值的整数,有的需要写10mA单位的原始值。写错一个数量级,请求就会被Source拒绝。我建议在代码里统一用原始值运算,注释里标明单位,避免不同版本芯片之间做移植时踩坑。

第三个坑是CC线质量问题。PD协商对CC线上的信号完整性有一定要求,用了劣质Type-C线或者转接头,可能出现协商失败或者频繁断开。调试阶段尽量用短而粗的线,排除物理层问题后再去查代码。

第四个坑是供电端不兼容。市面上的“PD充电器”鱼龙混杂,有些只是第3档固定输出,根本不是标准PD,有些虽然支持PD但实现有缺陷。测芯片、测代码都排除了问题,还是协商不成功,那就换个充电器试试。我一般手边常备三四个不同品牌的充电器做兼容性测试。

最后分享一个小技巧。调试CH224A/Q时,不要一上来就写完整业务代码,先把一个最简的IIC读取例程跑通,把状态寄存器、PDO数量和每个PDO的原始值都打印出来。确认这些基础信息全部正确,再去写“请求第几档”“动态切压”这些业务逻辑。这样出了问题,你能快速定位是协议层的问题还是应用层的问题,而不是在一个500行的工程里漫无目的地加打印信息。我每次换芯片型号、换充电器、改硬件板子,都会重复一遍这个过程,看起来多花十分钟,实际上省掉的是半天起步的排错时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 1:25:10

做那个类型的网站赚钱最稳?揭秘3类高转化站的成本与运营干货

做那个类型的网站赚钱最稳?揭秘3类高转化站的成本与运营干货 想靠网站搞钱,别光盯着页面做得漂不漂亮。很多老板问我:“我啥代码都不会,想做个站,到底花多少钱才不亏?” 这问题太典型了。自己不会代码想做网站,最大的坑不是技术,是选错方向。做错了,花几万块请人开发,上线后流量为零,那钱就真打了水漂。…

作者头像 李华
网站建设 2026/9/28 1:24:56

晶晨S905L3B电视盒子免拆刷机指南:从slimBOXtv烧录到救砖全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 1:24:53

设计方案参考网站安全自查3步走多少钱都省了

设计方案参考网站安全自查3步走多少钱都省了 改个需求建站公司拖一周,最后甩给你一句“服务器要维护”,气得你直拍大腿。这时候你才发现,之前为了省那点 多少钱…

作者头像 李华
网站建设 2026/9/28 1:24:41

宁波免费建站避坑指南:2026最新域名服务器部署防挂马实战

宁波免费建站避坑指南:2026最新域名服务器部署防挂马实战 网站突然被黑,打开全是赌博广告,后台密码怎么改都没用,日志里全是乱码请求。这种“网站被黑挂马不知道怎么办”的噩梦,很多刚接触【宁波免费建站】的新手都经历过。别慌,2026年的网络安全环境更透明,只要理清域名与服务器的底层逻辑,这套防黑体系就…

作者头像 李华
网站建设 2026/9/28 1:24:20

wordpress文章写html的3个实战案例与避坑指南

wordpress文章写html的3个实战案例与避坑指南 备案流程一头雾水?别慌,很多站长卡在服务器配置和代码混排上,导致网站加载慢、SEO排名掉。最近复盘了几个 实战案例…

作者头像 李华
网站建设 2026/9/28 1:23:55

济南槐荫网站开发公司选对源码,服务器配置才不翻车

济南槐荫网站开发公司选对源码,服务器配置才不翻车 域名解析报错?服务器一上线就卡死?很多槐荫区的老板找我咨询,第一句话都是“这域名服务器搞不懂,钱花了站还没影”。别慌,这行干了十年,我见过太多人卡在最后一步。其实问题往往不在技术本身,而在于你没拿到真正的 源码下载 权限,导致配置像盲人摸象。…

作者头像 李华