拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Type-C双向供电主从切换方案:LDR6500 IO电平硬切Sink/Source

Type-C双向供电主从切换方案:LDR6500 IO电平硬切Sink/Source

上周把一个 Type-C 双向供电原型板调通了,最折腾的地方反而不是 DC-DC,也不是功率路径,而是这个口到底该当“供电方”还是“受电方”。同一个 Type-C 口,插到电脑上要当 Sink,从电脑的 PD 口取电;插到充电器上又要反过来当 Source,给后面的设备送电。角色切来切去,协议芯片的身份识别和切换总是差点意思。折腾一圈之后,我最终选了最土但最稳的方案:用 LDR6500 的 IO 电平来控制主从切换。这篇文章就把这个落地思路完整拆开讲一遍,包括 Type-C 的身份究竟放在谁的引脚上、IO 电平是怎么左右这个身份的,以及从原理图到调试台会遇到哪些坑。适合正拿着 LDR6500 做 Type-C 取电、PD 诱骗、设备角色切换,或者准备画 Type-C 供电板的朋友。看完你应该能自己搭一个最小系统,并且知道怎么排查“插上没反应”“角色切不过去”这类问题。

1. Type-C 的身份不在协议里,而在 CC 引脚的两颗电阻上

1.1 身份协商的本质:Rp 和 Rd 一上一下

很多人第一次玩 Type-C 的时候,以为“这个口能不能供电、能不能被供电”是芯片通过复杂协议决定的,其实第一步恰恰是纯硬件行为。Type-C 的电源角色是靠 CC 引脚上的两颗电阻完成的:供电方(Source)在 CC 引脚上拉一颗电阻到自己的电源轨,这颗电阻叫 Rp;受电方(Sink)在 CC 引脚上下拉一颗 5.1kΩ 电阻到地,这颗电阻叫 Rd。

插上去的瞬间,Source 通过 CC 引脚读到的电压,就是电源轨经过 Rp 和 Rd 分压后的值。电压落在一个特定区间,Source 就认为“对面是个 Sink”,于是打开 VBUS;电压完全为 0,则认为线是空悬的。这个过程和串口检测设备在位很像,但更简单、更快。PD 协议本质上是叠加在这个电阻网络上的一层 BMC 编码通信,双方在 CC 线上协商电压、电流以及数据角色。换句话说,哪怕完全不跑 PD,Type-C 也可以只做“默认 5V 电源”,身份检测照样由电阻完成。

1.2 LDR6500 在身份体系里的位置

LDR6500 这种 PD 协议芯片,内部已经集成了 CC 检测比较器、协议解析逻辑和 Rd 网络。规格书里所谓的“CC1/CC2 检测”,指的就是它会判断 CC 线上有没有被对面的 Rp 拉起来。从角色上看,LDR6500 更偏 Sink:它检测到对面是 Source 之后,会主动发送 PD Request,请求把电压从 5V 提到 9V、12V 甚至 20V。很多 Type-C 诱骗线、电源触发板就是拿它做的,这也是它最常见的用法。

但标题里的“主从切换”,单靠 LDR6500 本身不够。LDR6500 决定的是“我作为受电端要多少电压”,而系统整体对外是 Source 还是 Sink,还要靠外部功率路径和一个 IO 电平来定。我在实际项目中用到的思路是:把 LDR6500 当作“非常会讨价还价的受电端”,由 IO 电平决定它是否参与工作;同时用另一路 MOSFET 控制 VBUS 的走向。这样一个小系统就能在“插上电脑取电”和“插上充电器给别人供电”之间切换。

1.3 电源角色和数据角色,别混为一谈

Type-C 的世界里其实有两套“主从”:电源主从(Source/Sink)和数据主从(Host/Device)。Rp/Rd 直接决定电源角色,但数据角色还要靠 USB 枚举。一个 Type-C 口可以同时是 Sink(正在充电),又同时是 Host(带着 U 盘),手机就是这样。

所以做“主从切换”之前,必须先把话说清楚:你要切的是电源身份,还是数据身份,还是两个一起切?LDR6500 只管电源侧。如果项目还需要切换 USB 数据通道,比如同一个口既要连电脑做 Device,又要接 U 盘做 Host,那就得在 D+/D- 上加模拟开关,由同一个 IO 电平或另一路 GPIO 控制。很多人在产品阶段翻车,就是没分清这两套主从关系,以为协议芯片把电源身份切好了,USB 枚举就自然正确,实际完全不是一回事。

2. IO 电平控制主从切换的硬件思路——为什么硬切比协议切更省心

2.1 为什么选 IO 电平而不是 I2C 寄存器

PD 协议本身有 PR_Swap 这种角色交换机制,可以让两个已经连接好的端口动态交换 Source/Sink 身份。问题在于,跑 PR_Swap 需要协议芯片支持、需要 MCU 维护协议状态、还需要处理各种对方不配合的情况,调试周期一下子拉长。

IO 电平方案完全不同。它是一个纯粹的物理信号:上电瞬间就定死,不需要初始化、不需要握手。在工业设备里,一个继电器触点、一个光耦隔离输入,甚至一个船型开关,都能控制身份。对很多固定场景来说——插到电脑上取电、插到充电器上供电——这种硬切足够用了,而且异常情况少。逻辑分析仪一看就知道当前 IO 是什么状态,排查问题非常直观。相比之下,I2C 配置地址、寄存器、时序,每一步都是潜在故障点。

2.2 IO 电平怎么左右身份:两条路

实际落地有两条路。

第一条,如果协议芯片本身支持双角色(DRP),IO 电平直接切换芯片内部的 Rp/Rd 状态。芯片自己完成 Source 侧或 Sink 侧的全部物理层逻辑,外部电路很干净。但这条路要求芯片选型时就选对,LDR6500 这种偏 Sink 的芯片不一定能直接这么用。

第二条,更常见也更现实的组合方案:LDR6500 负责 Sink 侧的 PD 协议,IO 电平控制外部功率路径和一个“Rd 接入开关”。当系统需要对外表现 Sink 身份时,IO 让 LDR6500 正常工作,CC 上的 Rd 接好,外部电源可以通过 VBUS 进来;当系统需要表现 Source 身份时,IO 先停止 LDR6500,同时把 CC 上的 Rd 断开,再把外部电源送到 Type-C 口。关键就在“断开 Rd”这一步,很多人的 Source 模式一开就短路,就是因为忘了 CC 上还挂着 5.1kΩ 对地电阻。

IO 电平状态系统对外身份LDR6500 在干嘛VBUS 通路方向
低Sink启用 CC 检测与 PD 协商外部电源进入系统
高Source停止抢电,CC 上的 Rd 被断开系统电源输出到外部

2.3 两块 IO 还能顺便选电压档位

LDR6500 这类芯片在很多固件里会提供两个 IO 引脚,用来选择 PD 请求电压档位。两个 IO 的组合能表达 4 个状态,正好对应常见的 5V、9V、12V、20V。比如:

IO1IO2请求电压(示意)
低低5V
高低9V
低高12V
高高20V

这段只讲原理。不同批次、不同固件版本的实际映射可能完全不一样,一定以你拿到的 LDR6500 规格书或供应商提供的参数表为准。我自己的习惯是拿到芯片先做一个小板验证,把两个 IO 分别拉高拉低,用示波器看 CC 线上的 PD 握手,确认固件行为再往下设计。

2.4 最小系统接线要点

一个可用的最小系统,大致包含这些节点:VBUS、GND、CC1、CC2、IO1、IO2,以及最终的电源输出。Sink 模式下,CC1/CC2 通过芯片内部的 Rd 网络挂在检测电路上,VBUS 从 Type-C 口进到系统电源路径;Source 模式下,CC1/CC2 外部改接到我们自己搭的 Rp 上拉网络,VBUS 则由系统电源送出。

这里有几个容易出现低级错误的地方。第一,不要在 CC 线上加太大的对地电容,CC 上要跑 BMC 编码的 PD 通信脉冲,电容一大,边沿变缓,协议容易握手失败。第二,IO 引脚不要在外部悬空,哪怕芯片内部有弱上拉,也建议外部再并一个 10kΩ 电阻,明确默认身份。第三,VBUS 路径必须加负载开关或者背靠背 MOSFET,不要让外部电源无控制地倒灌进系统。这几点是“画板前就要想清楚”的,不是等板子回来再调。

3. 落地实操:从原理图到示波器验证的完整流程

3.1 第一步,把 LDR6500 的 IO 行为查清楚

拿到芯片或者模块,第一件事不是画原理图,而是确认 IO 电平的有效极性。有些固件里,IO 拉低代表 Sink,拉高代表 Source;有些正好相反。还有些批次会默认把 IO 内部拉到某个固定电平,外部接法必须配合内部状态,否则你的“拉高”可能被内部拉低淹没了。

我的做法是:焊一块最小板,CC1/CC2 引出测试点,用一个可调电源模拟 Source,把 IO 分别接到 3.3V 和 GND,看 CC 电压和 VBUS 输出状态的变化。这一步花两个小时,后面省两个星期。尤其是从不同渠道买到的 LDR6500,固件版本可能不同,IO 行为也可能不同,不要想当然。

3.2 第二步,设计 CC 网络与 VBUS 功率路径

Sink 模式比较简单:CC 上的 Rd 网络让芯片自己处理,VBUS 进到负载开关,再进到系统。Source 模式真正麻烦:你必须在系统对外体现 Source 身份时,把原来连接在 CC 上的那颗 Rd 完全断开,同时接入自己的 Rp 上拉网络。

实际操作中,我一般用一个 P-MOS 或 N-MOS 做 Rd 断开开关,IO 电平低时 MOS 导通,Rd 接入地;IO 电平高时 MOS 关断,Rd 从电路上消失。VBUS 路径则用背靠背 MOSFET,这样无论哪边先上电,都不会出现电流倒灌。如果你觉得 MOSFET 驱动麻烦,也可以用现成的负载开关芯片,但要注意负载开关的导通电阻和最大电流,Type-C PD 动辄 3A、5A,压降不能太大。

3.3 第三步,固件状态机与 IO 读取

LDR6500 本身很多功能是硬件完成的,但主从切换需要一个控制方,通常是 MCU。下面是一段伪代码,展示 IO 电平控制主从切换的主循环思路:

// 伪代码:IO 电平控制身份切换 #include "ldr6500_driver.h" #define IO_MODE_PIN GPIO_PIN_5 typedef enum { MODE_SINK, MODE_SOURCE } sys_mode_t; sys_mode_t read_sys_mode(void) { // 外部电平决定身份:低电平=Sink,高电平=Source(具体极性以硬件为准) return gpio_read(IO_MODE_PIN) ? MODE_SOURCE : MODE_SINK; } void system_switch_role(sys_mode_t new_mode) { // 安全第一:先断开 VBUS,避免切换瞬间两边打架 vbus_path_disable(); if (new_mode == MODE_SINK) { ldr6500_sink_enable(1); // 启用 LDR6500 的 CC 检测和 PD 协商 cc_rd_connect(1); // 接上 5.1k Rd,对外表现为 Sink } else { ldr6500_sink_enable(0); // 停止 LDR6500 抢 VBUS cc_rd_connect(0); // 断开 Rd,避免把电源拉死 } delay_ms(10); // 等待 CC 电平稳定 if (new_mode == MODE_SOURCE) { vbus_path_enable(); // 把外部电源送到 Type-C 口 } } int main(void) { sys_mode_t mode = read_sys_mode(); system_switch_role(mode); while (1) { sys_mode_t cur = read_sys_mode(); if (cur != mode) { mode = cur; system_switch_role(mode); } delay_ms(100); } }

这段代码的核心思想是“切换身份之前先断 VBUS”。我踩过一次坑,直接把 IO 从 Sink 切到 Source,结果 LDR6500 还在抓着之前的 VBUS 不放,外部电源也同时送过来,两边电压一碰,适配器直接打嗝。先关路径、再切身份、最后送电,这个顺序不能反。

3.4 第四步,示波器验收

调试的时候,示波器至少抓三个点:CC1、CC2、VBUS。Sink 模式下,插入 Source 后 CC 应该由低变高,被对面 Rp 拉起来,然后出现一段 BMC 编码脉冲,那是 PD 协商过程;VBUS 从 0 跳到请求的目标电压。Source 模式下,CC 应该由我们自己的 Rp 网络维持在一个偏高的电平,接入一个 Sink 设备后,CC 会被对方 Rd 拉低到分压点;VBUS 则是我们主动送出的。

判断主从切换是否成功,最直接的就是看 CC 和 VBUS 的先后关系。如果 VBUS 起来了,CC 还没有稳定,说明身份检测和功率输出之间存在竞争条件,需要增加延时或者调整切换顺序。这一步不要节省时间,波形存下来,后面改板子的时候还能拿来对比。

4. 调板踩坑记录——CC 电阻、热插拔和 CH340 那些邻居

4.1 坑一:IO 浮空,身份随机

这是最隐蔽的坑。有些模块的 IO 引脚不做任何处理,直接留给用户,如果 MCU 还没启动或者用户忘了接,IO 就浮空。浮空状态下,芯片内部的弱上拉/弱下拉会随机决定一个身份,表现就是“这次插上去取电,下次插上去居然往外面送电”。

解决方式很简单:外部加一个 10kΩ 下拉或上拉,把默认身份固定下来。如果你希望默认是 Sink,就在 IO 上并联 10kΩ 到地;如果希望默认是 Source,就并联 10kΩ 到电源轨。MCU 接管之后,再通过 GPIO 主动输出覆盖这个默认状态。另外,MCU 和 LDR6500 共用电源域时,注意一下上电时序,别让 MCU 的 GPIO 在初始化之前输出一个不确定电平。

4.2 坑二:插上电脑没反应,多半是 CC 少了 5.1kΩ

用 Type-C 座子做设备端,最常见的问题是插上电脑完全没反应。绝大多数情况不是芯片坏了,而是 CC 引脚上的 5.1kΩ 下拉电阻没有放。主机只会通过 CC 引脚的电压判断是否有受电设备接入,如果 CC 悬空,电压不在 Sink 检测窗口内,主机的 VBUS 根本不会打开。

一个标准 Type-C 母座,USB 2.0 相关信号的引脚分组大致是这样:

引脚位置信号作用
A1/A12GND地
A4/B4VBUS总线电源
A5CC1身份检测 / PD 通信
B5CC2身份检测 / PD 通信
A6/B6D+USB 2.0 数据
A7/B7D-USB 2.0 数据

CC1 和 CC2 上必须各放一颗 5.1kΩ 下拉到地,尤其在只做 USB 2.0 或纯供电的设备端,这两颗电阻就是“身份证明”。我之前帮同事修过一台笔记本,Type-C 口插移动硬盘没反应,拆机量了一圈,不是主控坏,而是 CC 引脚附近的一颗 ESD 保护器件漏电,导致 CC 电压掉出检测窗口,系统一直认为没插设备。换掉那颗器件就恢复了。所以做 LDR6500 板子的时候,CC 网络上的保护器件结电容不要选太大,TVS 管的结电容尽量选 1pF 以下的。

4.3 坑三:D+/D- 要不要串电阻

网上经常有人问 CH340 这类 USB 转串口芯片接到 Type-C 座子上,D+/D- 需不需要串电阻。我的经验是:如果 CH340 和 Type-C 座在同一块板上,走线不超过几厘米,可以不串;如果通过线缆连接,或者板子走线较长、又没有良好的阻抗控制,那就在 D+/D- 上各串一个 22Ω 到 33Ω 的电阻,放在靠近芯片的一端。串电阻的作用不是限流,而是抑制信号边沿反射、减少 EMI。

更需要注意的是 D+/D- 和 CC 走线不要平行太长。CC 上的 BMC 脉冲频率不低,平行走线容易串扰进 D+/D-,导致 USB 枚举不稳定。如果只是 12Mbps 的 Full-Speed 设备,问题不大;如果跑 480Mbps High-Speed,就不建议乱加对地电容,保持走线短、参考地完整更有效。

4.4 坑四:切换瞬间 VBUS 打架

IO 刚切到 Source 时,如果对面正好也是一个 Source,比如两台适配器对插,两个 Rp 各自上拉,谁也不会先输,CC 电压会处在一个异常区间。更危险的是,如果两边都开了 VBUS,正极对正极,电流会从一个电源灌进另一个电源。

我的处理方式是:IO 切到 Source 后,延迟 20ms 再开 VBUS。这 20ms 内先用 ADC 读 CC 电压,如果发现电压异常高或者持续抖动,就认为对面也是 Source,此时回退到 Sink 模式,或者直接报错。这个检测逻辑不增加任何成本,MCU 一个 ADC 通道就能搞定。热插拔的时候也一样,VBUS 上不要瞬间硬切,加一个软启动,用小电流预充一下 Type-C 口的输出电容,能明显减少打火和电压跌落。

5. 从 Demo 到量产:状态机、防倒灌和几种值得做的扩展玩法

5.1 把切换逻辑写成状态机

原型板调通之后,不要停在“能跑就行”的状态。主从切换涉及到电源路径、协议协商、热插拔多种情况,必须用状态机把行为固定下来。我的状态定义大致如下:

  • IDLE:空载,VBUS 无输出。
  • SINK_ATTACH:检测到对面 Source 的上拉,LDR6500 开始工作。
  • SINK_NEGOTIATE:LDR6500 正在和 Source 协商电压。
  • SINK_READY:协商完成,VBUS 正常进入系统。
  • SOURCE_ATTACH:IO 切换为 Source,断开 Rd,等待对面 Sink 接入。
  • SOURCE_READY:检测到对面 Sink,VBUS 主动输出。
  • FAULT:过压、过流、倒灌或协商超时。

跳转条件主要依赖 IO 电平变化、CC 电压阈值和超时定时器。我习惯用一个 5ms 周期的轮询任务扫描这些状态,任何跳转之前先执行“断开 VBUS”这个动作。这样做的好处是逻辑清晰,每个状态都对应一组硬件行为,出问题的时候看状态寄存器就知道卡在哪一步。

5.2 功率路径可靠性设计

主从切换产品的可靠性,一大半在功率路径上。背靠背 MOSFET 是必须的,防止两个 Source 互灌;VBUS 入口和出口各放一颗 TVS,吸收热插拔浪涌;IO 电平控制线加一个 RC 滤波,比如 1kΩ 电阻串联 100nF 电容到地,防止干扰脉冲误切身份。

量产测试阶段,我建议在固件里加一条“身份回读”指令,让上位机或测试治具读取当前 IO 状态和身份状态。很多虚焊、电阻贴错的问题,靠这一条命令就能在生产线上筛掉。别小看这个细节,Type-C 座子是手工焊接重灾区,CC 电阻虚焊是“插上没反应”的第一大原因。

5.3 扩展玩法

这套“IO 电平控制主从切换”的思路,换一下外围电路就能套到好几个项目上:

  • 双向移动电源/户外电源:LDR6500 做受电侧的 PD 协商,IO 电平决定系统是给电池充电还是从电池放电,外部配一颗双向 DC-DC。
  • Type-C 调试器/串口工具:LDR6500 负责从主机取电,CH340 做串口,再配合一颗 TS3USB221 模拟开关切换 D+/D- 的数据通道,IO 电平控制模拟开关的选通方向。
  • 开发板 Type-C 供电口:一个 IO 决定请求 20V 还是 5V,配合板上的 DC-DC 给主控供电,避免上电时请求错误电压烧板。
  • 工业设备主从切换:用光耦隔离的 IO 信号控制身份,配合 PLC 的远程 IO 模块做角色切换,这在现场调试中比软件改地址稳得多。

5.4 什么时候别用 IO 电平硬切

IO 硬切也不是万能的。如果产品需要在运行时频繁动态交换角色,比如扩展坞在插拔不同设备时自动切换 Source/Sink,或者需要根据电池电量和外接设备状态综合考虑身份,这时候就需要换一颗支持完整 DRP/PR_Swap 的 PD 控制器,比如 STUSB4500、FUSB302 配合 MCU 跑协议栈。LDR6500 加外部 MOS 的硬切方案适合“上电定身份”的场景,不该拿去硬扛动态切换需求。

我个人在实际操作中的体会是,这套方案最大的优点就是“可预期”。IO 电平落下去,身份就定下来,不会因为协议栈状态混乱而出现两个口互相等对方的死局。第一次调切换时我总觉得协议芯片可以自己搞定一切,结果发现硬件上 Rd 没有断开,Source 模式一开,5V 直接被拉到地,适配器打嗝。后来老老实实按状态机做,把身份切换理解成“先把手里的刀放下,再决定自己是什么人”,问题就顺了。给后来者一个建议:画板之前先用 LDR6500 模块把 IO 行为摸清楚,用示波器把 CC 波形存下来,再动手设计功率路径。这比上来就画板、烧板后拿着万用表到处捅要省一个迭代周期。另外,网上搜“IO”会出来一堆磁盘性能、PLC IO 之类完全不相关的内容,搜 LDR6500 相关文章时注意别跑偏。

返回列表