六路互补PWM验证实验:死区配置与示波器实测全记录

发布时间:2026/10/11 1:05:43
六路互补PWM验证实验:死区配置与示波器实测全记录
做电机驱动、逆变器这类东西绕不开“六路互补PWM”这个坎。不管你是做三相永磁电机控制还是只想做一个三相异步电机的开环调速底层面对的都是同一件事用六路PWM去控制三相全桥里的六个功率管。我最早做这个实验的时候心里想的是“配置一下就能出波形”结果一上示波器就懵了——死区没配对、上下桥臂偶尔同时导通、占空比和预期差一大截最后查了一圈问题居然出在示波器探头地线上。这篇博文把我做“验证六路互补PWM”实验的整个设计思路、参数计算、实测步骤和排错过程完整记下来给正在调底层驱动的朋友做个参考。1. 实验背景与整体设计思路验证为什么比生成更重要1.1 为什么电机驱动离不开六路互补PWM三相电机或者三相逆变器的主电路典型结构是三相全桥六个功率管分成三组每一组构成一个桥臂分别连接电机的U、V、W三相。每个桥臂分为上管和下管上管导通时该相电压接近母线正端下管导通时接近母线负端上下管交替工作才能在该相输出一个可控的电压波形。这里有一个物理上的硬规矩同一桥臂的上下管绝对不允许同时导通否则电源正负极直接通过桥臂短路功率管会瞬间烧毁。这就是“互补PWM”存在的根本原因——上下管的驱动信号必须互为反相并且在切换过程中留出一段两者都关断的间隔时间。这个间隔时间就是死区时间一般用Td表示。六路互补PWM的意思就是六路开关信号分成三组每一组两两互补CH1和CH2互补控制U相上下管CH3和CH4互补控制V相CH5和CH6互补控制W相。这个“六路”不是说六路信号互相之间都有固定相位而是指三对互补输出。很多新人在看时序图时会把三组之间也要求成完全同步其实不一定具体相位关系要看应用——SPWM里三组之间有120度相位差SVPWM里则是由扇区状态机决定。做“验证”时第一步只验证组内互补关系第二步才验证组间相位。1.2 实验的目的不是“让PWM输出”而是“证明PWM符合预期”很多人把实验理解成“把代码烧进去看到波形动了就行”但验证实验有更高的要求。我做这个实验时给自己定了三个检测项第一六路输出的频率和占空比与设计值一致第二三组互补信号之间的死区时间符合设定值第三极性正确且在整个占空比变化范围内始终保持互补和死区。这三点都满足才能说这个PWM模块的配置是可信的后续才能放心地接功率板、接电机去调FOC或SVPWM算法。验证手段上我分了三个层次先看逻辑波形即直接在MCU引脚上测量3.3V或5V的电平信号这一步用来验证软件配置再看空载输出即接入驱动板但电机不接或接阻性负载用来验证驱动电路是否把逻辑信号正确转换成功率管的开关信号最后才接电机看相电流相电压。这样做的好处是一旦波形不对能快速隔离是软件问题还是硬件问题而不是拿着示波器在一堆线里乱猜。1.3 为什么用硬件PWM外设而不是让GPIO软件翻转这一节得专门说一下方案选型。我在不少项目里看到过用定时器中断翻转GPIO来“模拟PWM”的做法两路时还能凑合到六路互补就非常吃力。第一中断响应有不确定性两路死区只能靠软件延时延时期间CPU被占死第二频率稍微高一点比如20kHz每个周期中断多次CPU几乎没有余量处理控制算法第三如果翻转顺序写错高侧和低侧同时导通就会直接炸管。所以做六路互补PWM首选必须是带互补输出功能的高级定时器。带高级定时器的MCU典型的是Cortex-M内核里带TIM1/TIM8这类外设的型号。这类定时器在硬件上就支持两路互补输出、可编程死区插入、刹车输入、自动关断等机制。死区由硬件在对输出级控制时插入不需要软件干预既精确又不占CPU。对于验证实验而言用硬件外设还有一个好处配置完成后的波形是确定性的排错时只需要检查寄存器状态不用分析中断时序。如果你的MCU没有高级定时器也可以用外部死区芯片或FPGA来做但复杂度就不是一个量级了不在本文讨论范围。2. 实验准备硬件接线、软件初始化与示波器设置2.1 硬件清单与我的选择做这个实验最低配置是一块带高级定时器的MCU开发板、一个下载器、一台示波器。如果只验证控制信号不需要高压大功率电路但如果想看到完整的驱动效果建议再准备一块三相驱动板、一组阻性负载和一个直流电源。我第一次实验时用的是一块带高级定时器的通用开发板定时器时钟配到72MHz输出端在排针上引出来方便夹探头。示波器用的是100MHz带宽的4通道型号对10kHz级别的PWM来说这个带宽绰绰有余实际上50MHz也够用。如果有条件我强烈建议准备一个8通道逻辑分析仪。逻辑分析仪采样的是高低电平看不出模拟信号的质量但它在验证逻辑时序时有天然优势一次接6路甚至更多通道可以同时看到全部PWM信号还能直接测出每一路的频率、占空比、死区宽度效率比示波器四通道两轮测完高不少。我一般流程是先用逻辑分析仪做逻辑验证再用示波器看模拟细节比如上升沿的振铃、死区平台里的噪声等。2.2 接线和测量点的选择直接影响判断有很多人卡在“波形看起来不对”上其实是测量点选错了。控制芯片引脚和功率管栅极之间隔着驱动电路电平不同、参考地不同波形形状也不同。我在实验里是这样分的验证软件配置时探头直接夹MCU芯片的PWM输出引脚和开发板的GND验证驱动板时再测功率管的栅源极或者驱动芯片输出端的测试点。千万注意普通示波器探头是不隔离的如果去测量三相桥的高侧栅极探头地线夹到错误的参考地可能瞬间造成短路或者看到完全失真的波形这个风险比代码写错还高。探头地线的长度和位置对波形判读的影响我放到后面常见问题里细说这里先提醒一句多通道同时测量时所有探头的地线最好都接到同一个GND参考点不要一路接控制板地、一路接功率地否则地环路会把噪声引进来你会看到一堆没法解释的毛刺。2.3 示波器设置先用触发把波形“钉住”初学者拿示波器看PWM最常见的问题是波形乱跳。原因多半是没有设置触发电平和触发源。我习惯把CH1接U相上管信号然后设为触发源触发方式选择上升沿触发电平设为满量程的一半左右。如果信号是3.3V触发电平设在1.5V左右是5V就设在2.5V左右。这样每次都以CH1的上升沿作为时间基准开始扫描波形就能稳定显示。测量频率和占空比时建议用示波器自带的测量功能而不是肉眼数格子。把光标放在一个完整周期上读数会自动算出来。水平时基拖到周期的2到5倍比如10kHz周期是100us时基可以设置在200us/div这样屏幕上能看到两三个完整周期比较舒服。还要把采样模式调到平均模式我一般取16次或32次平均可以滤掉一部分测量噪声读出来的频率和占空比更接近真实值。这个习惯在做逻辑信号验证时特别好用。2.4 软件工程的基本结构软件部分用一个我自己的工程模板系统时钟初始化、GPIO初始化、定时器PWM初始化、主循环里修改比较值。GPIO初始化时要把六个输出引脚配置为复用推挽输出输出引脚不需要额外上拉配置成复用功能即可。这里特别要说一下高级定时器的MOE主输出使能位它控制所有PWM通道是否真正输出到引脚很多新手配置完寄存器发现引脚没信号就是忘了置这个位。初始化时还有一个容易被忽视的细节配置完PSC、ARR等预装载寄存器后需要主动产生一次更新事件把影子寄存器装载一遍否则部分配置要到下一个溢出周期才生效配置死区时尤其要注意这个时序。3. 定时器配置核心频率计算、死区时间与极性设置3.1 频率设计先定PSC还是先定ARR直接影响分辨率PWM频率由定时器时钟、预分频器PSC和自动重装载值ARR共同决定。向上计数模式下计数时钟 定时器时钟 / (PSC1)一个完整PWM周期 (ARR1) 个计数时钟所以频率公式是 f 定时器时钟 / ((PSC1) × (ARR1))。先用一个例子算一遍。我实验的目标频率是10kHz定时器时钟72MHz选择PSC0表示不分频ARR 72000000 / 10000 - 1 7199。这样每个周期计数7200次每次计数时间约13.89ns占空比分辨率是1/7200约0.014%足够精细。为什么我优先把PSC设为0、把ARR做大因为PSC越小计数脉冲越细占空比调节的步进越小。假设同样10kHz我把PSC设为71ARR设为99也能用但占空比每次只能调整1%调节分辨率差太多了。在做电机控制时要做到平滑调速低分辨率会导致电流波动。所以实验阶段就把定时器的分辨率往大了留后面写算法时更省事。// 以某带高级定时器的Cortex-M内核MCU为例定时器时钟72MHz // 目标PWM频率10kHz死区约2us占空比先设50% // 时基配置 TIMx-PSC 0; // 不分频 TIMx-ARR 7199; // 一个周期计7200次 - 10kHz TIMx-CNT 0; TIMx-EGR TIM_EGR_UG; // 产生更新事件让PSC/ARR在影子寄存器生效 // PWM模式向上计数PWM模式1CNT CCR时输出有效电平 TIMx-CCMR1 | (0x6 4); // CH1输出比较模式设为PWM模式1 TIMx-CCMR2 | (0x6 4); // CH2输出比较模式设为PWM模式1仅示意 // 50%占空比 TIMx-CCR1 3600; TIMx-CCR2 3600; // 死区配置DTG0x88对应约2us 72MHz TIMx-BDTR (TIMx-BDTR ~0xFF) | 0x88; // 使能输出CH1、CH1N高电平有效 TIMx-CCER | 0x1; // CH1使能 TIMx-CCER | 0x4; // CH1N使能具体位要看手册 // 最后使能主输出MOE TIMx-BDTR | (1 15); // MOE13.2 死区时间计算从需求到寄存器值死区时间的产生原因前面说过了重点是计算。高级定时器的死区发生器通常以一个基准时钟节拍tDTS为基础tDTS等于定时器时钟的周期。还是以72MHz为例tDTS 1/72MHz ≈ 13.89ns。要得到2us的死区时间就需要大约144个tDTS。但死区寄存器不是简单的线性编码常见MCU会把DTG[7:0]分成几个区间每个区间的步长不一样。我用某型号的高级定时器举例其编码规则如下DTG[7:5]等于000~011时死区时间DTG[6:0]×tDTSDTG[7:5]等于100或101时死区时间(64DTG[4:0])×2×tDTSDTG[7:5]等于110或111时死区时间(32DTG[4:0])×4×tDTS。目标2us即2000ns。带入第二档(64DTG[4:0]) × 2 × 13.89ns ≈ 2000ns也就是64DTG[4:0]约等于72DTG[4:0]8。所以DTG 0b10001000也就是十六进制的0x88。配置完成后实测死区约2us符合预期。如果目标死区是1us可以带入第一档DTG[6:0]×13.89ns ≈ 1000nsDTG[6:0]约等于72由于第一档最大支持到127所以DTG0x48实测接近1us。这些在手册上有更细的表格但理解了档位计算方式就不会被表格吓到。注意死区时间不是越大越安全。死区过大会让输出电压出现缺口等效占空比损失变大电流谐波和电机噪声增加死区过小则可能重叠导通直接炸管。工程上一般根据功率管的开关特性来定低压MOSFET对10kHz载波常用0.5~2usIGBT常用3~5us以上。实验阶段先取2us方便示波器观察稳定后再调小验证。3.3 极性、有效电平和空闲状态怎么设配置互补输出时还有个容易混淆的概念是有效电平。PWM输出可以配置为高电平有效或低电平有效对应CCER寄存器里的CCxP和CCxNP位。做实验时我建议先把极性统一配置成高电平有效也就是输出高电平时功率管导通。这样在示波器上看高电平的时间就是管子导通的时间非常直观。如果某个桥臂因为驱动电路是反相结构而需要配置成低电平有效也要保持上下两路的极性逻辑在最终电平上互补而不是简单地把寄存器里的互补位随便设置。空闲状态是另一个重要概念。刹车或初始状态时PWM输出应该处于什么电平电机驱动安全设计里通常要求空闲时上下管都关断而不是都导通。高级定时器一般有CCxE和CCxNE位分别控制互补两路的输出使能还有CCxP和CCxNP控制极性。在配置时确保使能的是互补输出通道而不是普通输出通道否则信号就不会出现在预期引脚上。这一点在从普通定时器迁移到高级定时器时特别容易踩我身边不止一个同事把CH1和CH1N接反查了半天。3.4 主输出使能MOE高级定时器的“总开关”高级定时器和普通定时器最大的区别之一是它有一个主输出使能位MOE来控制所有输出通道。如果MOE为0那么无论PWM配置得多完美引脚上都不会有任何电平变化保持空闲电平。这个位在BDTR寄存器里默认上电后是0必须在初始化最后把它置1。我遇到过一个非常经典的场景GPIO、时基、比较模式全查了一遍都是对的引脚就是没波形最后读寄存器才发现MOE位压根没写。所以我把MOE的检查放在初始化函数的最后一步并在调试时用调试器直接读BDTR寄存器的值确认。这是在配置代码时最容易忽略的步骤后面很多“输出恒为低”的报错都源于此。为了防止自己忘记我在工程里加了这样一段初始化顺序确保定时器先产生一次更新事件让所有影子寄存器把配置真正装载然后置位MOE。这里必须单独提一句修改比较值、死区、极性等寄存器之后最好也主动生成一次更新事件否则新配置可能还滞留在预装载寄存器里当前周期不生效看起来就像“改了没反应”。4. 实测过程从一对互补输出到六路SPWM的完整验证4.1 第一步先盯住一对互补输出的死区实验一开始我没有急着接满六路而是先把CH1接U相上管引脚CH2接U相下管引脚观察第一组互补输出。正确波形应该是两路方波周期相同、占空比接近且高电平时间错开两者有一段同时为低电平的平台这段平台就是死区。如果看到两路高电平有重叠那就是死区没生效绝对不能继续往功率级接否则一上电就可能短路。示波器里测量这组信号时可以打开脉宽测量对比正脉宽和负脉宽。以10kHz、50%占空比、2us死区为例上管导通时间应该是“半周期减去死区时间”也就是50us - 2us 48us左右对应占空比约48%。这个数值不是50%原因就是死区占掉了一部分导通时间。很多测试者看到这个偏差会误以为占空比配置错了其实这是互补PWM的正常形态。真正占空比错误的表现是导通时间和设定差很多或者在动态变化时出现跳变。4.2 第二步四通道示波器下如何覆盖六路信号四通道示波器看六路需要分两轮。第一轮把CH1、CH2接U相上下管CH3、CH4接V相上下管第二轮把CH1、CH2改为接W相上下管CH3、CH4仍接V相或接U相作为相位参考。由于第二轮和第一轮是不同时刻的测量中间的时序关系不能直接对比但可以以其中一个通道为触发基准分别记录两组波形的相对位置再在纸面或软件里拼起来。有的示波器支持断电保存可以把两组波形截图保存后在电脑上对齐做工程验证报告时也很方便。如果你有条件用8通道逻辑分析仪这步就会快很多。把所有通道接到六个PWM引脚再留一个通道接一个参考信号一开机就能捕获全部六路。逻辑分析仪的“解码”功能可以直接把每路脉冲宽度和占空比统计出来比人在屏幕上数格子可靠得多。我一般在做完逻辑分析仪验证后再用示波器抽查一到两组信号确认模拟电平没问题这样既快又不遗漏。4.3 第三步动态占空比下验证互补关系全程稳定固定占空比验证通过后还不能说明问题。互补PWM的难点在于占空比变化时上下管的导通时间此消彼长死区仍然要保持。可以写一段循环代码让占空比每200ms步进一次从10%逐步升到90%再用示波器的余晖模式观察屏幕上会留下所有过渡期的波形包络。正常情况下每组互补输出的高电平脉冲宽度整体平移但任意时刻上下管不会同时为高。如果需要更严格的验证可以临时把死区时间设得异常大比如10us。这样在示波器上死区平台一目了然你甚至可以用光标直接量出平台的宽度。设置大死区不是为了实际运行而是为了验证逻辑——把死区时间调到肉眼可见的尺度确认每个切换沿都正确之后再改回2us。这个方法是我常用的“放大验证法”特别适合在初期排查配置问题省不少时间。4.4 第四步带阻性负载验证功率级效果软件波形验证通过后我建议接一个阻性负载再测一次。三相星形连接的三个功率电阻是比较理想的负载阻值可以根据母线电压和想要测试的电流来选。以24V母线为例如果希望每相电流1A每相电阻可以选在8欧姆左右注意电阻功率要留足余量。此时示波器测电阻两端电压你会看到正负交替的电压脉冲宽度随占空比变化。因为死区的存在在电流从一个桥臂换到另一个桥臂的瞬间相电压会出现一个小缺口通常几百ns到几us这是正常现象不要当成故障。做带载测试时有一个安全习惯先把母线电压从低压开始比如先加5V确认电路不冒烟、电流在范围内再逐步升到目标电压。不要一上来就加全电压。这个习惯我到现在写进自己的实验清单里因为功率电路出问题往往是瞬间的低压预检能救回不少元器件。4.5 进阶验证SPWM正弦调制与三组相位关系把固定占空比扩展成SPWM是六路互补PWM验证的一个很好的收尾实验。做法很简单在程序里生成一个正弦查找表每个载波周期更新一次三相比较值三相之间相差120度。用示波器观察其中一组互补输出你会看到脉冲宽度按正弦规律变化上下管依然互补且死区保持。再观察三组上管的波形会发现它们之间有固定的相位差U、V、W依次滞后120度。这个实验做完六路互补PWM的基本验证就完整了因为你已经证明了三件事互补逻辑正确、死区正确、组间相位关系符合调制需求。后面在此基础上跑FOC或者方波控制PWM底层就不用再动了。我在做完这个实验后还是保留了SPWM的这段代码后面调算法时也经常拿来作为参照。5. 常见问题速查与排错思路实录先放一个我在实验过程中总结的速查表后面对应展开讲现象最可能原因快速排查方法输出恒为低或恒为高MOE位为0、GPIO复用错误、触发设置不对读BDTR寄存器确认MOE检查GPIO配置查示波器触发同桥臂两路同时为高死区未生效、极性配置反先逻辑负载复现重新初始化更新事件波形边缘振铃过冲探头地线过长换短地线弹簧做探头补偿实测死区与配置值不符探头延迟、DTG计算错误做deskew重新核对tDTS六路信号相位错乱相线顺序或定时器不同步固定占空比看顺序启用主从同步5.1 输出恒为高或恒为低先查三个地方这是整个实验里最常见的故障我把它放在第一位。原因通常出在三个地方一是GPIO的复用功能没有配好引脚仍处于模拟输入或普通推挽输出状态二是高级定时器的MOE位为0所有PWM输出被硬件屏蔽三是示波器触发电平设置不对信号其实存在但屏幕上看不到变化。判断方法是先用万用表测引脚静态电平如果引脚电平在变化而示波器看不到那就是触发或探头问题如果引脚确实不变再用调试器读定时器的BDTR和CCER寄存器。我整理了一个排查顺序先看时钟再看GPIO复用再看CCER里通道使能位再看BDTR里的MOE位最后看示波器触发。按这个顺序走基本能在十分钟内定位。不要一上来就怀疑芯片坏了我遇到过的芯片损坏案例很少绝大多数是配置和测量问题。5.2 互补两路同时为高死区去哪了这种波形是危险信号说明保护机制没有生效。原因要么是没有使用真正的高级定时器用的是普通定时器输出两路独立PWM然后直接把IO映射到驱动板看起来像互补实际无死区要么是死区寄存器确实配置了但改了寄存器后定时器没有产生更新事件新配置停留在预装载寄存器中没有生效。还有一种是极性配置反了高侧低有效、低侧高有效结果在示波器上看到高电平重叠。处理时第一时间断开功率部分让MCU只驱动逻辑负载然后在示波器上复现。确认使用的是高级定时器把DTG值重新写入并在初始化最后生成一次更新事件再读寄存器确认影子寄存器里的值。如果极性出问题把CCxP和CCxNP位对调后重新测试。我把这个问题的排查编成了一句口诀先确认是高级定时器再确认DTG生效最后检查极性。5.3 波形边缘出现振铃是电路问题还是测量问题看到波形上升沿和下降沿有过冲和振铃时不要急着改电路先检查测量手段。最常见的元凶是探头地线。标准探头配的长鳄鱼夹地线具有较大的电感高频信号在边沿变化时会产生谐振看起来就像真实的振铃。把鳄鱼夹换成探头自带的短地线弹簧直接勾在引脚旁边的测试点振铃往往会减轻甚至消失。还要做一次探头补偿把探头接到示波器的1kHz方波校准输出端调节探头上的补偿电容直到显示的方波顶角是平直的没有圆角和过冲。如果确认测量干净后振铃仍然明显那就要看真实电路。功率管的栅极驱动回路里PCB走线电感加上栅极电容会形成一个LC回路开关速度太快就会出现电压尖峰。处理方式一般是在栅极驱动电阻上并联一个小电容或者增大栅极电阻、降低开关速度。但在纯粹的逻辑信号验证阶段这类问题通常不用管先把测量问题排除就行。5.4 实测死区与配置值明显不符先校准探头再做判断有人配置2us死区实测出来3us就开始怀疑寄存器算错了。在排除寄存器计算错误之前先检查示波器探头延迟。不同探头、不同通道之间的传输延迟有差异测量纳秒级时间差时这点差异会直接影响死区读数。示波器通常有deskew功能可以用两个探头同时接同一个方波信号源校准两通道之间的延迟差校准完再测死区时间就准了。我实验时接了四通道每次都会做一次deskew尤其是要精确测量死区或相位差时这一步不能省。如果校准后误差还是偏大再检查DTG编码是否进入了预期的区间。比如我前面算过目标2us用0x88如果手滑写成0x48实测就是1us左右而不是2us。还有一个细节有些MCU手册里的tDTS不是定时器时钟周期而是定时器时钟经内部分频后的节拍计算前先确认tDTS的真实值否则整个表都会偏。我以前就是没注意这个内部PLL分频算出来的死区误差特别大后来对着寄存器位定义逐位核才找到问题。5.5 六路信号之间相位错乱别急着改代码如果三组互补输出各自都正常但组间相位和设计不一致最常见的场景是在SPWM下U、V、W三相的顺序接错。这不是PWM配置的问题而是驱动板到电机相线的连接顺序问题。验证方法比较简单把占空比设为固定值用示波器同时看三路上管信号确认它们在时间轴上的顺序然后在程序里交换比较值的更新顺序或者在硬件上调整相线连接。要注意记录清楚哪个通道对应哪一相否则很容易在调试板上绕晕。另外有些MCU的高级定时器存在“从模式”的概念多个定时器可以同步启动。如果六路时钟不是从同一个时基派生启动时差会导致相位抖动。验证实验中只用同一个定时器的六个通道一般不会有这个问题但如果用两个定时器各出三路就需要配置主从同步让两个定时器在同一个更新事件触发下启动。这个坑在后续做多定时器协调时会遇到我在实验记录里特别标注了。到这里整个实验的流程和坑位都讲得差不多了。我实际做完这个“验证六路互补PWM”的实验最大的收获反而不是那几行配置代码而是建立了一套调试习惯先把逻辑和功率分开验证再在功率级前做低压预检测量前先校探头、短地线排除测量误差每一个寄存器配置完都读回来确认不靠肉眼猜。这套习惯在后面调试电机驱动、开关电源、逆变器时帮了大忙。最后给新入坑的朋友一个建议第一次做这个实验时不要急着接电机也不要直接上高压先把六路逻辑波形在示波器上看明白死区、极性、相位都确认无误再接功率级。炸管往往不是因为你配置错了太多而是因为一个小错在高压大电流下被放大成了事故。