多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

USB PD调试实战:用逻辑分析仪抓取CC线波形与BMC解码全流程

USB PD调试实战:用逻辑分析仪抓取CC线波形与BMC解码全流程 这标题一看就知道是懂行的朋友出的。做USB PD相关的开发或者调试最头疼的就是用户态看着没问题物理层全是问号。寄存器里的状态、日志里的报错终究是别人嚼过的信息真到了充电协商失败、快充握手异常这种场景少了逻辑分析仪抓CC线上的原始波形你根本不知道问题出在哪儿。这篇文章我就把整套流程拆开讲从怎么接线、设置采样率到BMC解码原理再到怎么把一段裸波形还原成可读的PD报文全部走一遍。不管你是刚接触USB PD的嵌入式新人还是被PD快充问题折磨过的老工程师按这个思路去抓一次包很多之前只能靠猜的问题都会直接现出原形。1. 为什么抓USB PD波形从寄存器猜谜到眼见为实1.1 靠日志和寄存器排查PD协议问题的真实痛点USB PD协议协商不是一次简单的高低电平交互而是一个带状态机的完整通信过程。源端比如充电器和受电端比如手机、笔记本电脑需要先在CC线上建立连接然后通过交换Source_Capabilities、Request、Accept、PS_RDY等一系列消息才能在电压、电流档位上达成一致。这个过程是毫秒级完成的而且失败之后设备往往会反复重试。我见过很多同事排查快充问题的方式先看设备侧日志再读芯片的PD寄存器确认收到几条消息、发了几个ACK。看起来逻辑链路是通的但充电速度就是不达标或者握手成功率只有30%。这类问题的根源往往不在软件而是在物理层——CC线上的信号跳变沿不够陡、电平抖动、毛刺导致BMC解码误码或者SOP同步模式丢了接收端根本没把消息正确收进来。这种时候你去看寄存器它只会告诉你没收到有效消息但不会告诉你为什么没收到。只有把CC线上的波形抓下来一比特一比特地看才能真正定位问题。这也是为什么逻辑分析仪在PD调试里不是可选项而是刚需。1.2 为什么用逻辑分析仪而不是示波器很多人的第一反应是用示波器去抓CC线。示波器确实能看电压幅度、上升沿时间这些是逻辑分析仪做不到的。但在USB PD协议调试这个场景里逻辑分析仪有它不可替代的优势。首先是通道数和存储深度。一个PD协商过程可能包含十几次消息交互如果只抓十几微秒的波形根本不够用你需要连续采集几十毫秒甚至几百毫秒的数据。示波器的存储深度在这个量级下往往比较紧张而逻辑分析仪的深存储可以轻松记录几秒到几十秒的波形还能事后慢慢回放。其次是解码能力。USB PD的物理层编码是BMC如果靠人工对着示波器波形去解BMC那效率低得可怕。主流的逻辑分析仪软件比如Saleae Logic或者PulseView都支持协议解码功能。有些直接内置USB PD解码器选好通道就能把原始波形变成一帧一帧的消息节省大量时间。另外价格也是一个现实考量。入门级的逻辑分析仪几百块就能买到采样率20MHz以上协议解码够用。示波器要想达到同样的解码体验得上高端混合信号示波器价格完全不在一个量级。为了更直观我把两者的适用场景放一起对比一下对比维度逻辑分析仪示波器核心能力多通道、深存储、协议解码高精度电压测量、时序测量USB PD解码软件内置/脚本解码方便需要高端型号或后续处理长时间抓包轻松记录秒级波形存储深度受限通道数8/16通道常见通常2/4通道价格百元到几千元专业级上万元起步实际开发中我基本都是逻辑分析仪先上手确认协议层正常后如果怀疑信号完整性再上示波器看具体电压幅值、上升沿。1.3 逻辑分析仪选型参考手头设备怎么挑如果你还没入手逻辑分析仪我给几个选型建议。我自己用过Saleae Logic 8和国产的Kingst LA5016也试过用PulseView搭配便宜硬件各有各的适用场景。如果你主要做USB PD、I2C、SPI、UART这类协议调试采样率至少要保证20MHz以上。前面会详细算这个数值的来由这里先给结论USB PD的BMC编码最小脉冲宽度大约是1.67微秒20MHz采样率相当于每个最小脉冲至少采30多个点解码软件才有足够的分辨率去恢复比特流。在软件层面Saleae Logic自带的USB PD协议解析器是非常好用的选好CC通道就能自动识别SOP、消息类型和内容。PulseView作为开源方案虽然内置的USB PD解码器不如Saleae完善但配合Python脚本处理导出数据一样能完成分析而且它对硬件的要求更低一些几十块钱的开发板就能变成采集设备。考虑到很多读者接触的第一台逻辑分析仪就是PulseView兼容设备后面我会把手工解码脚本解码这条路也讲透这样即使你的设备没有内置PD解码器也完全不影响实操。另外还有一点容易被忽略逻辑分析仪的探头和线材质量很重要。USB PD的CC线信号幅度并不大大概在0.25V到2V之间摆动如果探头线材阻抗不稳定、接触不良抓出来的波形会惨不忍睹。尽量选择原装探头或者屏蔽良好的测试线别在这个地方省钱。2. 抓包前必须吃透的基础CC通道与BMC编码原理2.1 USB PD的物理通道CC1与CC2为什么信号是这样跳的USB PD和普通USB一个很大的不同是它多了一根用于通信的Configuration Channel线。Type-C接口里有两根这样的线分别叫CC1和CC2。在握手阶段Source设备通过Rp上拉电阻、Sink设备通过Rd下拉电阻在CC线上形成特定的分压电平。协商成功后PD通信就通过这根线进行。所以抓USB PD波形本质就是要抓CC线上的信号如果是一根Type-C线缆还要注意区分CC1和CC2哪根正在通信。CC线上的信号是单端的以GND为参考。通信时电平会在高低两个状态之间快速切换高电平大约在1V上下具体取决于供电策略。逻辑分析仪判定逻辑“1”和“0”依据的是一个阈值电压超过阈值算高、低于阈值算低。这个特点决定了我们抓取时要注意共地并且要了解CC线的参考地必须在同一系统内否则波形完全没法看。实际抓取时你可以选择在Source端的CC引脚上接探头也可以在Sink端接取决于你想观察哪个方向的消息。需要注意的是CC1和CC2不是同时工作的设备会选择一个作为主通信通道。如果不能确定是哪一根两个通道一起抓最稳妥。2.2 BMC编码一个自带时钟的“摩尔斯电码”USB PD在CC线上用的编码方式叫双相标记编码英文是Biphase Mark Coding缩写就是标题里的BMC。如果想在逻辑分析仪上正确解读波形理解BMC编码规则是绕不开的一步。BMC的规则其实很简单每个比特周期内信号的起始边界一定有一个跳变这是为了让接收端提取时钟。而比特中间有没有额外的跳变则用来区分“0”和“1”。如果传输逻辑“0”比特中间不再跳变整个比特周期内电平保持不变如果传输逻辑“1”比特中间还会再跳变一次所以一个比特周期内会出现一次额外的翻转。从这个规则可以推出一个很有意思的结论逻辑“0”在比特周期内表现为一段较宽的电平保持高电平或低电平持续约3.33微秒而逻辑“1”在比特中间发生翻转单段电平宽度只有约1.67微秒。也就是说电平保持时间长的对应“0”保持时间短的对应“1”。接收端靠边界处的固定跳变恢复时钟靠中间有没有跳变读出数据位。为什么USB PD要选BMC而不是简单的NRZ因为BMC有自同步能力不需要在传输链路上单独传时钟信号而且比特流里始终包含高频跳变成分直流分量相对稳定对单线传输来说很友好。你在逻辑分析仪上看到的BMC波形就像一段高高低低的“方波信号”但里面其实藏着一整个协议栈的信息。2.3 USB PD的帧结构SOP、Header、CRC32与EOP把CC线上的BMC波形解码成比特流之后下一步是从比特流里切出完整的数据帧。USB PD报文在物理层上按这样一个顺序组织Preamble前导码用来让接收端完成时钟同步通常是1010交替的比特序列SOPStart of Packet包起始同步模式标识后面的内容是真正的PD消息规范里定义了SOP、SOP、SOP等不同版本用于区分通信对象Header16比特长度的消息头里面携带消息类型、数据对象数量、消息ID、端口角色和电源角色等信息Data Objects数据对象数量不定0到7个每个32比特比如Source_Capabilities消息里的PDOPower Data Object就是一串数据对象CRC324字节的循环冗余校验校验范围从SOP之后到CRC之前的所有比特EOPEnd of Packet包结束标识。拿到解码后的比特流之后识别SOP是关键一步。SOP是一组特定的同步模式普通数据里几乎不会自然出现所以接收端一看到这个模式就知道“新包来了”。识别出SOP之后就能顺藤摸瓜读Header、数据对象然后按CRC32校验数据完整性。看起来有点复杂但实际操作中逻辑分析仪的协议解码器会帮我们直接完成这一切。之所以还要懂帧结构是因为当解码器失效、或者你想自己写脚本做深度分析时这些就是唯一的依靠。3. 实操准备接线、采样率与采集参数设置3.1 安全且正确的接线方法从Type-C上找到CC线接线是整个实操里最容易翻车的一步。不要一上来就想着把逻辑分析仪直接怼到Type-C母座上先确认你要抓的设备和线缆类型。如果你抓的是带Type-C接口的电源适配器最稳妥的方式是打开外壳在Source控制器的CC引脚上飞线出来。控制器的CC引脚通常有丝印标注或者查阅芯片手册确认实测下来这样抓到的信号最干净。如果不想拆外壳也可以买带测试点的Type-C转接板那上面会引出CC1、CC2引脚直接夹上去就行。连接顺序是这样逻辑分析仪的GND先和被测设备的GND接在一起这是绝对前提。然后把逻辑分析仪的一个通道接到CC1上如果条件允许另一个通道同时接到CC2上。最后再上电触发采集。很多新手第一次抓不到波形问题就出在没共地上或者接了CC线但没接GND导致参考电位浮动。接线时还有几个细节逻辑分析仪探头的地线夹子尽量短避免引入噪声测试线不要和VBUS的高压线绑在一起容易带来串扰如果抓的是已经协商过的链路要等设备重新握手才能抓到通信过程所以一般先接好线再给设备上电或者拔插一次电源触发重新协商。3.2 采样率怎么设1.67微秒最小脉冲背后的数学采样率设置直接决定了你能不能正确解码BMC。前面提到了USB PD的比特率是300kbps即每秒30万比特每比特周期约3.33微秒。按照BMC编码规则逻辑“1”在比特中间有跳变意味着最短的电平保持时间只有1.67微秒。根据奈奎斯特采样定理理论上要采集至少2倍于信号最高频率的采样率才能恢复波形即约1.2MHz采样率就不会丢信息。但工程上这个理论值远远不够因为采样点刚好错开跳变沿是常有的事。我个人的经验是至少保证每个最短脉冲有8到10个采样点换算下来就是10MHz到20MHz。用20MHz采样率抓BMC波形1.67微秒的最窄脉冲对应大约33个采样点足够让解码软件稳定判定沿的位置。如果是快速观察、只做肉眼确认10MHz也勉强可用但碰到抖动严重的信号就容易误码。我在实际项目里统一设置成20MHz既有余量又不会让采集文件大得离谱。另外一个重要参数是采集时长。PD协商过程通常在几十毫秒内完成我一般设置50毫秒到200毫秒的采集窗口足够把一次完整的协商抓下来。如果你的电力适配器有周期性重试机制可以把窗口拉得更长。注意采样率越高、时长越长数据量越大要保证电脑内存和软件能扛得住。3.3 Saleae与PulseView采集设置实战从空波形到捕获协商全过程以Saleae逻辑分析仪为例完整流程是这样的。先打开Logic软件在通道列表里选中你接CC1的通道设置采样率为20MHz采样时长设为100毫秒。然后在触发设置里选择上升沿触发触发通道指向CC1。这样做的目的是让软件在CC线出现第一次跳变时才开始记录避免一堆空闲波形占满存储空间。设置完成后先点击开始采集然后给被测设备上电或者重新插拔Type-C线缆。等到设备开始PD协商CC线上的BMC波形就会出现。采集结束后你会在软件界面上看到一长串脉冲波形这就是原始CC线通信数据。如果用的是PulseView步骤类似在设备下拉菜单中选择你的逻辑分析仪只要是sigrok兼容的硬件就行添加一个数字通道并接到CC1同样设置16MHz或20MHz采样率开启上升沿触发再点击Run。PulseView的优势是开源免费解码协议可以通过插件扩展虽然自带的USB PD解码支持有限但导出波形数据后结合脚本分析一样能完成任务。我建议新手第一次实操时先不要急着加解码器而是看着原始波形试着找到Preamble那串规则的1010方波再试着肉眼辨认SOP附近的异常跳变模式。这个过程虽然慢但能帮你把BMC编码和实际波形对应起来对后续理解协议解码非常有帮助。4. BMC解码实战三种方法还原USB PD报文4.1 方法一直接使用Saleae内置USB PD协议解析器在Saleae Logic软件里抓完波形后点击界面右侧的“”按钮添加一个协议解析器。在解析器列表中找到“USB PD”把它分配给CC1所在通道软件就会自动开始解码。几秒钟之后解码结果会以协议帧的形式叠加显示在波形上方每一行就是一帧完整的PD消息包含SOP类型、消息类型、关键字段等。我通常会触发一次充电器上电然后观察解码输出第一条看到的往往是Source发送的Source_Capabilities消息紧跟着是Sink的Request消息然后Source回复Accept最后Source发送PS_RDY表示电源就绪。这四帧就是一次最简单的PD握手流程。解析器还会把CRC校验结果显示出来如果出现CRC错误说明物理层传输有问题。这时候回去看波形经常能发现某个电平段的保持时间明显偏离理论值或者中间有毛刺这就是BMC误码的根源。Saleae解析器的好处是省时省力适合快速定位宏观问题。但它的缺点是封装好的你没法知道它内部是怎么从比特流里找SOP的。真遇到解码不出来或者解出来全是乱码的情况还是得靠手工方法往下挖。4.2 方法二手工从波形还原比特流以一段模拟波形为例工具帮你解完只是手段自己能从裸波形里还原出一帧报文才算真正理解USB PD。下面我用一段模拟波形来演示完整的解码思路。假设逻辑分析仪抓到的波形经过去毛刺处理后得到下面这一小段高/低电平序列1表示高0表示低1010101010101010 1110011100111001 0110010110100101第一步是找边界跳变。BMC编码里每个bit的起始处必然有一次跳变所以可以把连续相同电平看成一个个时间片段然后以“两个相邻跳变之间是否还能再见到跳变”来区分bit。更直观的算法是算出每个电平段的持续时间3.33微秒左右的是逻辑“0”1.67微秒左右的是逻辑“1”。比如序列里出现了连续的“111”段说明这中间是两次逻辑“1”连在一起中间那次跳变正好是第一个1的bit中间跳变。第二步是恢复原始比特流。按这个规则拆解下来上面的电平序列会变成一串二进制数据。我们要的SOP模式就藏在这串比特流的开头某处。由于SOP在规范里有固定模式而且前面接的是Preamble所以找到1010交替结束后第一次出现的非规则模式基本就是SOP的位置。第三步是切帧。认出SOP之后从SOP结束后的第一个bit开始数出16比特作为Header再按Header里指示的数量读出数据对象最后读出32比特的CRC32直到遇到EOP。整个过程有点像按图索骥但真的走一遍之后你对协议的帧结构会非常清晰。手工解码的局限也很明显当一帧里包含几十个数据对象、几百个比特时人工数bit非常容易出错。所以这个方法适合理解原理、验证小段数据实际大批量分析还是得靠脚本。4.3 方法三写Python脚本完成BMC解码附可直接跑的代码如果你手里的是PulseView这类不带PD解码器的设备别急着放弃。逻辑分析仪软件一般都能导出CSV文件每一行是一个采样点的电平值。基于这些数据用Python写一个解BMC的脚本是完全走通的方案。下面这份代码我实际跑过核心逻辑是把采样点转换成01序列检测跳变位置按固定bit周期切出每个bit再根据bit中间有无跳变判定是1还是0。import csv import sys # 参数根据实际采集设置调整 SAMPLE_RATE 20_000_000 # 20MHz BIT_RATE 300_000 # USB PD是300kbps BIT_SAMPLES SAMPLE_RATE // BIT_RATE # 每个bit的采样点数约66个 THRESHOLD 0.65 # 电压阈值根据波形实际幅度调整 def read_csv_levels(filepath): levels [] with open(filepath, r) as f: reader csv.reader(f) header next(reader, None) # 跳过头 for row in reader: if len(row) 2: continue try: v float(row[1]) except ValueError: continue levels.append(1 if v THRESHOLD else 0) return levels def decode_bmc(levels): bits [] i 0 n len(levels) while i BIT_SAMPLES n: segment levels[i:i BIT_SAMPLES] # 统计该bit周期内是否存在中间跳变 mid_start BIT_SAMPLES // 4 mid_end 3 * BIT_SAMPLES // 4 mid_half segment[mid_start:mid_end] transitions 0 for j in range(1, len(mid_half)): if mid_half[j] ! mid_half[j-1]: transitions 1 bits.append(1 if transitions 1 else 0) i BIT_SAMPLES return bits if __name__ __main__: levels read_csv_levels(sys.argv[1]) bits decode_bmc(levels) # 打印前200个bit便于观察Preamble、SOP print(.join(str(b) for b in bits[:200]))这段代码不一定能直接套用到所有波形因为实际信号可能有毛刺、抖动bit周期也不会严格等宽。更健壮的做法是先用一段滑动窗口检测跳变沿再根据跳变间隔聚类出1.67us和3.33us两类时间宽度从而恢复数据。但在拿到真实波形、准备手工深入分析时上面这个雏形足够当起点。脚本解码的最大价值是批量处理。你可以把一整个协商过程的CSV导出然后用脚本解出所有bit再按帧结构把SOP、Header、数据对象全部提取出来生成一份类似协议分析器的报告。这比在一块屏幕上手动滚动波形高效得多也是我处理疑难问题时的常用手段。5. 抓包与解码常见问题排查实录5.1 波形完全空白八成是共地和触发的问题这是新手最常遇到的情况。明明接了CC线点开始采集结果波形一片空白偶尔有一两个毛刺。我排查这类问题有一套固定顺序。先看逻辑分析仪输入指示灯是否正常、通道是否选对、GND是否和被测设备共地。CC线信号以GND为参考如果地线断开所有电平判断都会失效。其次看触发设置使用上升沿触发时如果设备在点击采集之前就已经完成了协商那么之后不再有上升沿自然抓不到任何数据。解决办法是把触发模式改成“无触发足够长的时长”或者先点击采集再重新上电、拔插线缆人为制造一次握手过程。最后检查探头接触是否牢固尤其是使用杜邦线或者夹子时接触电阻变大也会让信号衰减得面目全非。5.2 抓到了波形但解码全是乱码采样率和阈值的取舍如果你能看到波形但Saleae解码器输出的全是乱码或者CRC疯狂报错通常要往两个方向排查。第一是采样率是否不足。前面算过1.67微秒的最小脉冲至少要保证8到10个采样点。如果采样率只有2MHz或4MHz逻辑分析仪会漏掉很多跳变沿BMC解码自然乱套。在Saleae里把采样率改为20MHz再抓一次很多问题立刻消失。第二是信号电平是否落在阈值边缘。USB PD的CC线高电平和低电平之间的余量并不大如果被测设备的CC线上电平不稳定或者上位机软件设置的阈值偏高/偏低就会导致采样结果出现误判。Saleae允许手动调整数字通道的阈值电压PulseView则需要通过校准或者手动测出实际电平范围。一般来说把阈值设在CC线高电平和低电平的中间位置最合适但前提是你要知道这两个电平的实际值可以先观察一段波形的幅度再做判断。5.3 解码出来了但少帧或丢包SOP识别和干扰排查有时候波形和解码都是正常的但解出来的报文明显缺少某些应该出现的帧比如Source_Capabilities后面对应的Request没有出现。这类问题往往是物理层丢帧不是解码器的锅。BMC接收端是通过检测SOP来判定新包开始的如果SOP前几个bit因为毛刺、地弹或者串扰被破坏接收端就会忽略整个包。排查手段是回到原始波形放大看SOP附近的细节看是否存在多余的高频毛刺。如果毛刺出现在上升沿或者下降沿附近可以考虑在代码层面用中值滤波去抖如果是由于探针接触不良导致的就先处理物理连接。另外一个隐蔽原因是采集时间窗口太短。PD协商过程中有时会有一些延迟比如Sink设备在发送Request之前会做内部电压测量如果采集窗口恰好在这个间隙停止记录看起来就像丢帧了。解决办法是把采样时长放宽到200毫秒以上甚至1秒宁可多抓数据也不要在时间窗口上省事。6. 实操心得与后续进阶建议没有什么比亲自动手更有价值做USB PD调试这几年我越来越觉得抓波形这件事情本身不是目的真正的目的是建立“问题-现象-信号”之间的直接对应关系。每次遇到难啃的PD握手问题我都会先问三个问题是否看到了完整的协商状态机是否有某条消息的CRC校验失败CC线上的波形是否存在不该出现的跳变把这三个问题放到逻辑分析仪上去验证往往比翻半天寄存器更有效。如果你刚开始接触USB PD我建议按这个顺序练习先用带内置解码器的逻辑分析仪抓一次完整的充电协商见识一下Source_Capabilities到PS_RDY的标准流程然后用手工方法解一小段波形把BMC编码、SOP、Header这些概念和物理信号对上号最后再考虑写脚本做批量分析完善自己对BMC解码的理解。这个过程下来你不仅能排查问题还能对协议本身有更深的认识。再往后如果你想进阶可以重点关注几件事一是PPS可编程电源协商过程中的APDOAugmented PDO交互那里面数据对象的解析更复杂二是VDMVendor Defined Message消息尤其是供应商自定义指令的抓取和解析三是线缆emark相关通信这类通信使用SOP和普通SOP报文混在一起解码器如果没处理会直接跳错。这些都是USB PD协议里比较深的水区但基本原理还是BMC、SOP、Header、CRC这套东西大框架吃透了剩下的只是填细节而已。最后分享一个小技巧抓PD波形的时候我会同时把逻辑分析仪的一个通道接到CC1、另一个通道接到CC2剩下一个通道留出来接VBUS。这样一次采集既能观察CC线上完整的协议交互又能看到VBUS电压何时上升、CC通信和功率输出之间的时序关系。很多电源切换类的疑难问题靠这个多通道布局一眼就能定位。工具是死的思路是活的真正把逻辑分析仪用好的工程师都是把通道、触发、解码这些功能组合起来针对具体场景打组合拳的人。希望这篇文章能帮你少走一些弯路。
返回列表