物理层基础:CC线、BMC编码与电压等级

做PD协议开发,第一关就是摸透物理层。我见过不少同事一上来就扑到报文解析上,回头发现波形对不上,供电握手失败——十有八九是CC线上的细节没吃透。这一章我们就从最底层的CC线讲起,把BMC编码和电压等级一起理清楚。

CC线的物理特性

CC线,全称Configuration Channel。Type-C接口里有两根CC线——CC1和CC2。为什么是两根?因为USB-C可以正反插,只用一根的话,反插就断了。两根线在Source端各接一个Rp上拉电阻,在Sink端各接一个Rd下拉电阻。插反了?自动切换,不耽误事儿。

我的习惯:调试时先用万用表量CC1和CC2对地的电压。如果两边都在0V附近,大概率是没接Rp或Rd;如果一边是0.35V一边是0.9V,那通常就是Source检测到了Sink的存在,开始协商了。

CC线上的直流电平决定了供电方向和控制角色。我们平时说的CC电压,其实就是Rp和Rd分压后的结果。Type-C规范里给了一张表——不过我用实际参数给大家捋一下。

角色 电阻类型 标准值 作用
Source Rp(上拉) 10kΩ / 22kΩ / 56kΩ 拉高CC线,标识供电能力
Sink Rd(下拉) 5.1kΩ ±1% 拉低CC线,标识自己是设备端
EMCA(线缆) Ra 1kΩ ±1% 标识线缆带芯片,协商电子标记

这里有个容易忽略的点:Rd的精度要求±1%。我曾经遇到过一批Sink板子,用5%的电阻,结果Source认成了Ra状态,硬是卡在5V 0.5A不肯升压。所以各位做原理图时,Rd一定要选1%贴片电阻,别抠那几分钱。

BMC双相曼彻斯特编码原理

说完了直流电平,咱们再看数据怎么在CC线上传递。PD协议在物理层用的是BMC编码——Biphase Mark Code,双相曼彻斯特编码。你把它理解为一种自同步的编码方式就行。

怎么工作的?每一比特时间单元内,必定有一次电平跳变。

  • 传输逻辑1:在码元开始处额外增加一次跳变。也就是说一个周期内跳变两次(开始跳一次,中间再跳一次)。
  • 传输逻辑0:只在码元开始处跳变一次,中间保持电平。
说白了:看跳变次数就知道是0还是1。一次跳变是0,两次跳变是1。时钟信息就嵌在跳变里,接收端不需要单独传时钟。

接收端用一个简单的计数器,测两次跳变之间的时间就能恢复时钟。这也带来了一个限制——BMC通信的速率不能飘太远。PD规范里规定标称波特率是 300 kbps,容差±0.5%。实测300kHz的时钟,差个1.5kHz就可能导致采样错位。

我在一个量产项目里就吃过这亏:Source端的晶振用了普通±50ppm的,Sink端用了±25ppm的,看着都满足0.5%——但温度一上来,两边偏差加起来快0.3%,再叠加上芯片内部PLL的抖动,偶尔就丢包。后来全部换成了温补晶振(TCXO),问题才消除。

BMC的物理波形长什么样?我画了一张简单的时序图,大家看箭头跳变。

BMC编码波形示意(NRZ对比) NRZ: 1 1 0 0 1 1 0 0 1 1 0 0 BMC: 1(两跳) 0(一跳) 1 0 1 0 t 红色为0,绿色为1。每比特开始必有跳变,1在中间多跳一次。

这条红线是NRZ(非归零码)——直接高低电平表示0和1。下面绿线是BMC。注意看,BMC每个比特开始处都有一段跳变(上升或下降),而NRZ在连续相同比特时电平不变。这就是BMC自带时钟的原因——接收端只要监测跳变沿,不需要额外的时钟恢复电路。

注意:BMC的起始跳变方向没有限制,上升沿或下降沿都可以。实际芯片在解码时只看跳变次数,不看跳变方向。我在一个项目中遇到过示波器触发的问题,因为起始跳变方向不确定导致示波器误触发,后来改用边沿模式+电平触发才稳定。

电压/电流等级划分

说完编码,回到CC线上的电压信号。Type-C规范把CC线上的电压划分成几个明确的档位,Source通过检测CC电压来判断Sink的供电能力需求。反过来,Sink也通过CC电压知道自己能申请多大电流。

我把它整理成以下表格,大家写代码判断逻辑时直接参考。

CC电压范围(V) 含义 对应电流能力(Source侧) 典型Rp值
0.00 ~ 0.15 未连接 / 接地 无 –
0.15 ~ 0.35 Ra(线缆检测) 线缆标记,未供电 1kΩ 对地
0.35 ~ 0.55 Rd(Sink默认) 0.5A 56kΩ Rp
0.55 ~ 1.00 Rd(中等电流) 1.5A 22kΩ Rp
1.00 ~ 1.65 Rd(大电流) 3A 10kΩ Rp
1.65 ~ 2.60 Vconn供电 线缆芯片供电 –

这张表是PD握手前的基础。实际工作中,Source端ADC采样CC电压时一定要做滤波,否则瞬间噪声可能让判断误入其他区间。我有一次发现充电器明明标称3A,接上负载后只输出0.5A——查了好久,最后发现Source的ADC采样窗口刚好踩在电噪声的正半周期,读到了0.49V,误判为56kΩ。加了一个简单的10ms软件防抖就解决了。

电流能力与电压曲线的联动

上面讲的电流等级仅适用于PD协议对外协商前的基础供电。一旦进入PD报文交互,电流能力就由Source_Capabilities消息内的PDO来决定了,不再是靠CC电阻来猜。但底层物理层依然依赖CC线上的BMC通信来传递这些报文。

这里梳理一个关键逻辑链条:

  1. 物理连接:Source通过Rp拉高CC线,Sink通过Rd拉低CC线,形成分压。
  2. 基础供电:Source根据检测到的CC电压,决定是否输出5V基础电压和相应电流。
  3. BMC通信:在CC线上叠加BMC编码信号,开始PD报文交互。
  4. 协商升级:通过GoodCRC、Request、Accept等报文,最终确定正式电压电流。

每一步都依赖于CC线的正确物理特性和可靠的BMC解码。所以我的建议是:在做PD协议栈之前,先用示波器抓一段CC线上的BMC波形,确认边沿陡峭、幅度足够、噪声不多。我自己每个新平台都会抓500ms的BMC波形存档,方便后面排查问题。

一个小经验:动手验证时,可以给CC线串联一个1kΩ电阻再入示波器,不然探头电容可能拖慢跳变边沿,导致解码失败。

本章内容到这儿,下次拿起示波器看CC线时,你就能一眼看出电压对应哪个电流等级,BMC波形里0和1怎么分清了。