简介:这份PDF资料围绕TYPE-C接口中的CC(Configuration Channel)功能展开,面向硬件工程师、嵌入式开发者及对USB Type-C协议感兴趣的进阶学习者,帮助厘清正反插识别、接口配置、PD供电协商与Alternate Mode切换等核心机制。资源包内含1个PDF文件,大小约878KB,以图文结合的方式系统梳理CC1/CC2引脚在插入检测、DFP与UFP类型判断、Rp/Rd电阻配置、VCONN供电及Emarker线缆识别中的作用,并延伸至DisplayPort Alt Mode的两种模式与激活流程。目前已有6685人学习下载,内容涵盖VL160等典型MUX电路框图、PD2.0至PD3.1的功率档位与PPS微调机制,以及DP Alt Mode通过VDM协商切换数据路径的完整思路,适合作为接口协议入门与硬件调试的参考笔记,便于快速建立TYPE-C CC功能的知识框架。
1. 从一根线说起:为什么你的设备插上没反应
很多人第一次接触 TYPE-C CC 功能,是在一块自己画的转接板或者一个快充诱骗器上。板子焊好,插上充电器,设备纹丝不动,示波器一戳,CC 引脚上干干净净,连个电平都没有。这时候才意识到,TYPE-C 不是「插上就能用」的接口,它背后有一套完整的握手协议,而 CC(Configuration Channel,配置通道)就是这套协议里最核心的那根线。TYPE-C CC 功能本质上解决的是三件事:谁供电、谁受电、供多少电,以及这根线到底能不能传数据。它决定了设备是作为 Source 还是 Sink,决定了充电功率能跑到 5V/3A 还是 20V/5A,也决定了插反了为什么还能正常工作。如果你正在做带 TYPE-C 接口的硬件、写 PD 协议固件,或者只是想搞明白为什么同一根线插不同设备效果天差地别,那 CC 这一块绕不过去。下面按「先搞懂它在干什么、再动手测、最后踩坑」的顺序讲透。
2. CC 引脚到底在干什么:从上下拉电阻到 PD 握手
2.1 两个电阻决定设备角色
TYPE-C 接口里有 CC1 和 CC2 两根配置通道线,线缆里只有一根 CC 会被实际连通,另一根用于翻转检测。设备角色靠上下拉电阻区分:Source 端(供电方)在 CC 上挂一个上拉电阻 Rp 到 VBUS,Sink 端(受电方)挂一个下拉电阻 Rd 到 GND。当两者插在一起,CC 线上就形成一个分压,Source 通过检测这个电压判断对方是 Sink,Sink 通过检测电压判断对方是 Source 以及能提供多大电流。
常见做法是:Source 端 Rp 用 56kΩ 表示默认 USB 电流(500mA/900mA),22kΩ 表示 1.5A,10kΩ 表示 3A。Sink 端 Rd 固定 5.1kΩ。这个电阻组合是 TYPE-C 最基础的「我是谁」声明,没有它,后面所有 PD 协商都无从谈起。
提示:很多翻车案例就是 Rd 焊成了 5.1kΩ 以外的值,或者干脆忘了焊,导致 Source 检测不到有效下拉,直接不输出电压。
2.2 翻转检测与线缆方向识别
因为 TYPE-C 支持正反插,CC1 和 CC2 在插座上的位置是对称的。Source 端会同时在 CC1 和 CC2 上提供 Rp,但只会在其中一根上检测到 Rd。检测到 Rd 的那根 CC 线被定义为 CC,另一根则作为 VCONN 使用(给线缆里的 e-Marker 芯片供电)。这个机制让设备不需要机械防呆就能自动适配方向。
实际调试时,如果你发现设备只有一面能工作,另一面没反应,大概率是只处理了一路 CC,没有做 CC1/CC2 的切换检测。正确做法是两路都采样,用模拟开关或者 MCU 的两个 ADC 通道分别判断。
2.3 PD 协议在 CC 上的 BMC 编码
基础的角色和电流声明靠电阻就能完成,但一旦涉及电压高于 5V、电流大于 3A,就必须上 USB PD 协议。PD 通信是在 CC 线上跑 BMC(Biphase Mark Coding)编码的差分信号,速率 300kbps 左右。Source 和 Sink 通过交换一系列数据包来协商电压和电流:Source 发 Source_Capabilities,Sink 回 Request,Source 再发 Accept 和 PS_RDY,最后 VBUS 才升到目标电压。
这个过程不是一蹴而就的,中间任何一步超时或者 CRC 校验失败,协商就会回退到默认 5V。用示波器抓 CC 线,能看到一串串脉冲,那就是 BMC 波形。用逻辑分析仪配合 PD 协议解码器,可以逐包看到协商内容。
2.4 用万用表快速判断 CC 状态
在动手写固件之前,先用万用表把 CC 静态电平量一遍,能排除大部分硬件问题。步骤如下:
- 不插任何设备,测 Source 端 CC1 对 GND 电压,应该是 Rp 上拉后的接近 VBUS 的电平(具体取决于 Rp 和万用表内阻)。
- 插上 Sink 设备,再测 CC1 和 CC2 对 GND 电压。其中一根应该降到接近 0V 附近的分压值,另一根保持高电平。
- 如果两根都高或者两根都低,说明电阻配置有问题或者线缆内部短路。
# 用万用表手动测量步骤(无代码,仅记录流程) # 1. 红表笔接 CC1,黑表笔接 GND,记录电压 V1 # 2. 红表笔接 CC2,黑表笔接 GND,记录电压 V2 # 3. 插上受电设备,重复步骤 1 和 2 # 4. 正常情况:插上后一根 CC 电压明显下降,另一根基本不变 # 5. 异常情况:两根都下降或都不变,检查 Rd/Rp 焊接和线缆通断这段流程没有代码,但它是所有后续调试的基础。电压值本身不是重点,重点是「有没有变化」和「哪一根在变化」。如果静态电平都不对,后面 PD 协商根本不会启动。
2.5 用 MCU 的 ADC 读取 CC 电平并判断角色
如果你用 MCU 做 Source 端,需要周期性采样 CC1 和 CC2 的电压,根据分压值反推对方接的是哪种 Rd。下面是一段伪代码逻辑,展示判断流程:
// 假设 VCC 为 3.3V,ADC 12 位,Rp 为 10kΩ(3A 档) // Rd 为 5.1kΩ,分压后 CC 电压约为 VCC * Rd / (Rp + Rd) // 实际电路中 Rp 上拉到 VBUS 或 VCC,需按实际供电计算 #define ADC_MAX 4095 #define VREF 3.3f float read_cc_voltage(int channel) { int raw = adc_read(channel); return (raw / (float)ADC_MAX) * VREF; } void detect_role(void) { float v_cc1 = read_cc_voltage(CC1_CH); float v_cc2 = read_cc_voltage(CC2_CH); // 如果某一路电压在 0.4V ~ 1.2V 之间,认为检测到 Rd if (v_cc1 > 0.4f && v_cc1 < 1.2f) { // CC1 检测到 Sink,CC2 作为 VCONN active_cc = CC1; } else if (v_cc2 > 0.4f && v_cc2 < 1.2f) { active_cc = CC2; } else { // 没有检测到有效 Sink,关闭 VBUS 输出 vbus_disable(); } }这段代码的关键参数是电压窗口。不同 Rp 值对应不同分压,10kΩ 配 5.1kΩ 时,如果上拉到 5V,分压约 1.67V;上拉到 3.3V,分压约 1.1V。实际阈值要根据你的上拉电压和电阻精度来标定,不能直接抄。另外 ADC 采样要有滤波,否则插拔瞬间的抖动会导致误判。
3. 动手搭一套 CC 通信测试环境:从诱骗器到逻辑分析仪
3.1 最小系统:一块 Source 板加一块 Sink 板
要验证 CC 功能,最直接的办法是搭一对 Source 和 Sink。Source 板可以用现成的 PD 电源模块,Sink 板可以用带 TYPE-C 接口的开发板,但最好是自己画一块最小板:Source 端放一个 TYPE-C 母座,CC1 和 CC2 各接一个 Rp 到 VBUS,VBUS 用可调电源供电;Sink 端放一个 TYPE-C 公头或母座,CC1 和 CC2 各接一个 Rd 到 GND,VBUS 接电子负载。
这样搭的好处是每个节点都能单独测。比如你想验证 5V/3A 档位,就把 Source 端 Rp 换成 10kΩ,Sink 端 Rd 保持 5.1kΩ,上电后测 VBUS 是否正常输出,CC 分压是否在预期范围。
3.2 用逻辑分析仪抓 PD 协商波形
静态电阻只能验证基础角色,PD 协商必须抓波形。常见做法是用支持 PD 协议解码的逻辑分析仪,探头接 CC 线和 GND,采样率至少 1MHz 以上。抓到的波形导入解码软件,能看到 Source_Capabilities、Request、Accept 等数据包。
如果没有专用解码器,也可以用示波器看 BMC 波形的大致形状:一串宽度不等的脉冲,代表 0 和 1。但手动解码不现实,还是建议用带协议栈的分析仪。抓包时注意触发条件设成 CC 线下降沿,否则可能抓不到完整的协商过程。
3.3 用 Python 脚本解析 PD 数据包
如果你有原始的逻辑分析仪导出数据(比如 CSV 格式的时间戳和电平),可以用 Python 做简单的 BMC 解码。下面是一个简化示例,只展示思路:
# 简化版 BMC 解码思路,实际 PD 协议要复杂得多 # 输入:list of (timestamp, level),level 为 0 或 1 # 输出:解码后的比特流 def bmc_decode(edges): bits = [] prev_time = None for ts, level in edges: if prev_time is not None: duration = ts - prev_time # BMC 用跳变沿表示时钟,脉宽约 3.3us 对应 300kbps # 这里只做示意,真实解码需要处理差分和 CRC if duration > 2e-6: bits.append(1 if level == 0 else 0) prev_time = ts return bits # 实际使用时要先做边沿检测,再按 PD 包结构解析 # 包括前导码、SOP、包头、数据、CRC、EOP这段代码只是示意,真正的 PD 解码需要处理差分信号、前导码同步、4b5b 编码和 CRC 校验。但思路是一样的:先把边沿时间戳转成比特流,再按包结构切分。如果你只是想做产品验证,直接用现成分析仪更省事;如果想深入理解协议,自己写一遍解码器收获很大。
3.4 参数怎么设:Rp/Rd 选型与 VBUS 阈值
| 参数 | 典型值 | 作用 | 注意点 |
|---|---|---|---|
| Rp(Source) | 56kΩ / 22kΩ / 10kΩ | 声明默认/1.5A/3A 电流能力 | 精度建议 1% 以内 |
| Rd(Sink) | 5.1kΩ | 声明自己是受电设备 | 必须接,否则 Source 不输出 |
| VBUS 默认 | 5V | 未协商前的安全电压 | 协商成功后才升压 |
| PD 协商电压 | 9V/15V/20V | 按 Request 调整 | 升压前确保负载能承受 |
| CC 采样率 | >100kHz | 捕捉 BMC 脉冲 | 太低会丢包 |
这张表里的值不是随便选的,Rp 的阻值直接对应 Source 能提供的最大电流,Sink 端 Rd 固定是因为协议规定。VBUS 升压前一定要确认后级电路支持,否则 20V 直接灌进 5V 器件就是冒烟。
4. 避坑与排查:CC 不通信的五个血泪经验
4.1 现象:插上后 VBUS 有 5V 但设备不充电
原因:CC 分压不对,Source 检测到的 Rd 值不在有效窗口内,可能 Rd 焊成了 10kΩ 或者虚焊。解决:断电测 Rd 阻值,确认是 5.1kΩ,补焊或更换。
4.2 现象:只有一面能充电,翻面就没反应
原因:只处理了一路 CC,另一路悬空或没有切换逻辑。解决:检查 CC1 和 CC2 是否都接了 Rp/Rd,MCU 固件是否两路都采样。
4.3 现象:PD 协商到一半就退回 5V
原因:BMC 波形畸变,可能是 CC 线走线太长、没有做阻抗匹配,或者电源纹波太大干扰了通信。解决:缩短 CC 走线,加 22Ω 串联电阻做端接,VBUS 加足够滤波电容。
4.4 现象:逻辑分析仪抓不到 PD 包
原因:触发条件设错,或者探头地线没接好。解决:触发设成 CC 下降沿,地线尽量短,采样率提到 2MHz 以上。
4.5 现象:Source 端 VBUS 一直输出,插不插都一样
原因:Rp 一直上拉,MCU 没有根据 CC 检测结果控制 VBUS 开关。解决:在固件里加逻辑,只有检测到有效 Rd 才使能 VBUS,否则关闭输出。
5. 进阶技巧:用 CC 日志反推线缆质量与兼容性
5.1 从协商日志看线缆 e-Marker
带 e-Marker 的线缆会在 CC 上通过 VCONN 供电,并返回线缆能力信息。抓包时如果看到 Discover_Identity 和 Discover_SVID 的交互,说明线缆有 e-Marker。没有 e-Marker 的线缆只能跑 3A 以下,超过 3A 的协商会失败。你可以通过日志里有没有这些包来判断线缆是否支持 5A。
5.2 用脚本统计协商成功率
如果你在做兼容性测试,可以写一个脚本自动跑多轮插拔,统计每次协商到目标电压的成功率。下面是一个伪代码框架:
# 伪代码:自动插拔测试并统计 PD 协商成功率 import serial import time def run_pd_test(cycles=100): success = 0 for i in range(cycles): # 控制继电器模拟插拔 relay_off() time.sleep(0.5) relay_on() time.sleep(2) # 等待协商完成 # 从串口读取 MCU 上报的协商结果 result = serial_readline() if "PD_SUCCESS" in result: success += 1 relay_off() print(f"成功率: {success}/{cycles} = {success/cycles*100:.1f}%") # 关键参数:插拔间隔要大于 PD 协商超时时间,一般 2 秒足够 # 如果成功率低于 95%,需要检查线缆、电源和固件重试逻辑这个脚本的核心是自动化重复插拔,把玄学问题变成统计数据。如果某根线缆成功率明显偏低,基本可以判定线缆质量有问题。
5.3 兼容性矩阵:不同 Source 和 Sink 组合
| Source 类型 | Sink 类型 | 预期结果 | 常见异常 |
|---|---|---|---|
| 标准 PD 电源 | 手机 | 正常快充 | 无 |
| 标准 PD 电源 | 自制 Sink 板 | 按 Request 升压 | Rd 未接导致不输出 |
| 自制 Source 板 | 手机 | 5V 慢充 | Rp 档位不对导致电流受限 |
| 自制 Source 板 | 自制 Sink 板 | 可协商到 20V | 固件超时导致回退 |
这张矩阵是我自己测试时记录的,每次换组合都重新跑一遍,能快速定位是 Source 问题还是 Sink 问题。
5.4 一个习惯:先量电阻,再抓波形,最后看固件
我调试 CC 问题的顺序从来不变:第一步万用表量 Rp/Rd 和 CC 对地阻值,第二步示波器或逻辑分析仪看静态电平和 BMC 波形,第三步才去翻固件代码。大部分问题在前两步就能定位,直接看代码容易陷入「以为协议写错了其实是电阻焊反了」的坑。这个顺序帮我省了很多后悔药,希望帮到你。
本文还有配套的精品资源,点击获取