公司动态

LAT1517比较器锁存导致PWM逐周期限流失效的排查与修复

📅 2026/8/29 19:18:07
LAT1517比较器锁存导致PWM逐周期限流失效的排查与修复
调试一块基于LAT1517的电机控制板时我遇到一个特别迷惑的现象PWM 一跑起来比较器只在第一个 PWM 周期正常触发之后就像被按了暂停键后续周期的比较结果完全丢失。示波器上看的波形很干净PWM 本身没问题比较器输入信号也确实在每个周期都跨过了阈值但只有第一个周期有响应。用一句话概括就是比较器在每个 PWM 周期只触发第一次比较。这个现象听起来像什么很多人第一反应是中断标志没清、或者比较器配置有问题。我一开始也这么想但在 LAT1517 上完整排查下来发现真正的坑在“比较器输出锁存”和“PWM 周期同步清零”这两个外设细节的配合上。这篇文章把整个排查链路、根因和最终的修复配置完整记录下来给正在用 LAT1517 以及同类带“比较器 PWM”联动方案的 MCU 做电机、电源、变流器开发的朋友一个参考尤其是用比较器做逐周期限流或过流保护的人。1. 复现现场第一个PWM周期正常之后比较器触发全部丢失1.1 最小复现环境在这块 LAT1517 板子上比较器 CMP0 的正输入端接的是母线电流采样电阻放大后的电压负输入端接到内部 DACDAC 输出值设成了过流阈值。PWM 用定时器中心对齐模式频率 20kHz周期 50 微秒。比较器的输出同时做了两件事一是映射到 PWM 故障保护输入当过流时硬件直接封锁 PWM 输出二是产生比较器中断用于让固件记录过流次数并做状态处理。这个架构在电机控制里太常见了。母线电流逐周期检测、故障保护硬件动作、固件只在背后记一笔。可是上电实测时问题就出来了。手动把负载调到过流状态第一次过流时故障保护正常动作PWM 输出被封锁固件里面过流计数也加了 1。然后我清零故障状态、重新恢复 PWM再次把负载调到过流按预期应该再次触发故障保护。结果没有任何反应比较器中断也不进来过流计数停留在 1。反复试了很多次规律完全一致每次上电复位后只有第一个 PWM 周期内的过流信号能触发比较器后面的全部丢失。好在这不是偶发问题而是稳定复现这对排查来说反而是好事。复现类问题最怕一次好一次坏稳定复现意味着根因是确定性的剩下就是一层层剥开。1.2 先做三个外围排除在碰寄存器之前我先把最容易出问题的外围环节排除掉。第一是信号源。直接把比较器正输入接到一个可调直流源手动让电压从阈值以下慢慢拉到阈值以上。第一次拉高时比较器能触发但触发之后我把电压降回阈值以下再往上拉第二次却不再触发。这个实验直接把“PWM 相关”的因素绕开了说明问题出在比较器自身的行为上而不是 PWM 时序叠加出来的假象。第二是电源和参考电压。比较器用的是模拟电源和内部 DAC 参考我用万用表确认了模拟电源纹波正常、DAC 输出稳定没有出现电压漂移导致阈值变化的可能。第三是引脚配置正输入端没有接错也没有复用冲突。在这个项目里比较器输入使用的是专用模拟引脚不会像普通 GPIO 那样有上拉或复用干扰。这三个外围排除做完重心就收回到比较器外设本身的配置和行为上。接下来我先从最容易下手的软件层开始排查。2. 软件排查中断标志和ISR不是“真凶”2.1 比较器中断的本质是“事件触发”MCU 里比较器的中断通常不是“电平触发”而是“事件触发”。比较器内部有一个比较结果当结果从一种状态翻转到另一种状态时会产生一个上升沿或下降沿事件这个事件才用来置中断标志。所以如果比较器的输出状态一直维持在高电平或者低电平不变是不会有新的中断产生的。放到这个项目里理解就是第一次过流比较结果从 0 变成 1产生跳变沿中断标志置位ISR 执行之后如果比较结果一直保持 1哪怕 PWM 还在跑、输入电流还在过流状态也不会再有新的跳变沿中断自然不会再触发。所以“只触发第一次”从软件事件角度看是说得通的。但问题来了我的 PWM 是连续的电流信号在每个周期都会在过流和正常之间来回变化为什么比较结果不会跟着翻转这就是后面要深挖的重点。2.2 ISR里加GPIO翻转做验证为了验证中断是不是真的没进来我在 ISR 里加了一个 GPIO 翻转。这个动作很朴素但非常有效。我在每次比较器中断里翻转 PC2 引脚用示波器观察这个引脚。第一次过流时PC2 翻了一下之后无论怎么制造过流条件PC2 都不再翻转。这说明 ISR 确实只执行了一次。同时我读了一下比较器状态寄存器发现中断标志位已经是 0说明中断标志本身没有挂死。很多人遇到“中断只触发一次”第一反应是“中断标志没清”。这里我用读寄存器的方式先确认了标志位是 0不是 1。如果标志一直是 1那确实会阻塞下一次中断但标志是 0说明不是软件层面阻塞的问题。这个区分很重要否则后面容易绕弯路。2.3 边沿触发与电平触发的区分排查过程中我还注意到一个细节如果比较器中断配置为“边沿跳变触发”那么在锁存模式下只有第一次从无效到有效的跳变会被识别。如果把中断配置成“电平触发”又会面临另外一种坑——只要比较结果保持有效中断就会一直被断言ISR 可能被疯狂进入或者被硬件合并成一次处理具体行为取决于芯片实现。对于这个项目来说ISR 只进来一次中断标志又没有被挂死说明软件层已经排除了嫌疑。接下来必须去看比较器输出本身的波形不能再停留在寄存器层面猜。软件层已经给了足够多的信息但真正的证据在硬件管脚上。3. 硬件联动排查比较器输出电平的锁存行为3.1 比较器输出不止是“通知CPU”LAT1517 这类主打电机控制的 MCU比较器输出通常不是只有“中断”这一条路。它内部有触发交叉矩阵或者专用路由可以把比较器输出直接送到定时器的故障保护刹车输入。这意味着当过流信号到来时硬件可以在几个纳秒内封锁 PWM而完全不需要软件介入。我第一次过流时 PWM 被关断就是这个硬件链路在工作。这个链路也带来了一个排查难点当比较器输出被锁住时PWM 故障保护已经触发PWM 本身已经不在正常输出状态。所以示波器上看到“PWM 停了”到底是比较器持续触发导致的还是比较器只触发了一次、PWM 被封锁后没恢复这两者现象相似但原因完全不同。3.2 同时抓PWM与比较器输出我把示波器的两个通道分别接到 PWM 输出引脚和比较器输出引脚位置方便的话可以直接接内部比较器输出的映射引脚。结果非常清楚第一次过流时PWM 立刻被封锁比较器输出从低电平跳到高电平但之后即使我把过流信号撤掉让输入电压回到阈值以下比较器输出依然保持在高电平没有回跳。这一步是整个排查里最关键的证据。如果比较器是正常的“实时比较”那么在输入电压回到阈值以下时输出应当立刻回到低电平。但实际输出一直保持高电平说明这个比较器外设不是直通模式而是处在“输出锁存”的状态。3.3 顺手排除了滞回比较器在看输出不回跳时有一个最常见的原因必须排除滞回比较器。滞回迟滞会让比较器在阈值附近产生一个死区避免输入信号在阈值附近抖动时输出反复跳变。如果我把比较器配置了迟滞而且迟滞值设得很大就可能出现输入低于阈值之后必须比阈值低很多输出才恢复。这种情况下虽然输出看起来“卡住”了但其实是迟滞在起作用不是锁存。我的配置里迟滞档位很小按手册给的迟滞窗口计算输入电压回到阈值下方 0.5 毫伏以内就应该恢复输出但实际输入已经远低于阈值了输出依然保持。所以迟滞不是主因。到这里基本可以确认比较器输出被某个“保持机制”锁住了。剩下的问题就是这个保持机制是怎么来的以及为什么 PWM 周期没有把它清掉。4. 根因定位锁存模式缺少PWM周期同步清零4.1 手册里那几行容易被跳过的文字翻 LAT1517 用户手册的比较器章节在输出模式控制部分能看到类似这样的描述比较器输出可以配置为直通模式、锁存模式、或由特定定时器事件同步清零。很多项目里工程师看到“锁存模式”就下意识觉得“这是故障锁存保护用的正合适”于是直接选上但没有继续往下看“锁存模式下的清零方式”。这个“清零方式”就是问题所在。锁存模式下比较器输出从无效跳变为有效之后会一直保持有效直到满足某个清零条件。清零条件通常有三种软件写 1 清除、读取状态寄存器后自动清除、定时器周期事件同步清除。我的初始化代码里只配了“输出锁存使能”没有配置任何清零源。结果就是比较器第一次触发后永久保持有效后续所有周期里的比较动作即便发生输出端也没有新的跳变沿中断和故障保护自然不再响应。4.2 三种输出模式的行为对比为了把这个问题讲得更清楚我用一张表格对比一下常见模式下比较器输出的行为输出模式比较结果翻转时输出第一次触发后输出状态典型用途直通模式立即跟随输入变化输入恢复则输出恢复实时过零检测、快速保护锁存模式无清零第一次翻转后锁存保持有效直到软件干预故障锁存、自锁保护锁存模式 定时器周期同步清零每个周期开始时被清零周期内允许再次翻转在 PWM 周期边界恢复无效逐周期限流、峰值电流保护表格里第三行就是电机控制里最常见的“逐周期限流”用法每个 PWM 周期开始时比较器输出被同步事件清零如果这个周期内出现过流比较器输出变有效触发保护下一个周期开始时输出再次被清零这样每个周期都能独立判断一次过流。我实际期望的行为是第三行而配置里实际生效的是第二行。4.3 为什么“第一次”一定会触发再补一个小的解释为什么这个配置下第一次触发总是正常的。上电时比较器输出锁存位默认是无效状态也就是说比较结果初始为 0。第一次输入过流时比较结果从 0 变 1产生一个有效的跳变沿锁存器把这个 1 锁住。这个过程完全正常所以第一次触发看起来“没问题”。问题出在第二个周期。理论上如果 PWM 周期事件能把锁存器清零比较结果就会回到 0下一个过流事件就能再次产生从 0 到 1 的跳变。但因为没有配置同步清零或软件清零锁存器里的 1 一直保留即使 PWM 周期事件已经产生比较器输出端依然还是 1。于是后面所有周期的过流信号在输出端看来都是“已经是 1 了无需再次上报”。用人话来讲这个配置下比较器只负责告诉你“有一次从正常到过流的跳变”之后它就认为你已经知道过流了不需要再报告。它做的是故障锁存而你需要的是逐周期检测。两个应用场景对输出行为的语义要求完全不同混用就是我这个坑的根源。4.4 用调试器做关键验证确认根因的最好实验是在比较器第一次触发后用调试器手动把输出锁存位清零。结果立竿见影清零之后下一个 PWM 周期又恢复了一次触发然后再次锁住。反复操作每次都一样。这基本就是从行为上验证了根因判断。到这里问题不再神秘剩下的就是选择一个合适的修复路径。5. 修复与扩展周期清零和软件清除两条路径实测5.1 路径A使能PWM周期同步清零第一个修复方案是在比较器配置里把“输出清零事件源”选择为对应的 PWM 定时器周期事件。LAT1517 的交叉矩阵里通常会有这个选项选择后每个 PWM 周期开始时硬件会自动清除比较器输出锁存让比较器在下个周期内能够重新判断。修复前后的配置差异用伪代码写出来就是这样的/* 修复前的比较器配置伪代码 */ cmp_config.positive_input CMP_IN_AMP_OUT; cmp_config.negative_input CMP_IN_DAC; cmp_config.output_mode CMP_OUT_LATCH; /* 锁存模式 */ cmp_config.latch_clear_source CMP_CLEAR_NONE; /* 没有指定清零源 */ cmp_init(CMP0, cmp_config);/* 修复后的比较器配置伪代码 */ cmp_config.output_mode CMP_OUT_LATCH; cmp_config.latch_clear_source CMP_CLEAR_TIM1_PERIOD; /* 周期事件同步清零 */ cmp_init(CMP0, cmp_config);修改完成后我重新测试把负载调到过流状态示波器上看到比较器输出在每个 PWM 周期都会出现一个有效脉冲PWM 故障保护也按设计动作固件里的过流计数从 1 变成了连续累加。这才是“逐周期比较”应该有的行为。这里有一个细节值得留意同步清零事件必须和 PWM 定时器正确绑定。如果你的 PWM 用的是定时器 TIM1就必须在配置里明确指定 TIM1 的周期事件作为清零源。配置错定时器的话清除事件不会发生症状和原来一样。5.2 路径B软件周期间清除锁存如果芯片不支持定时器同步清零或者你用的 PWM 是由非标准定时器产生的还有一个退而求其次的方案在 PWM 周期中断或者溢出中断里软件写 1 清除比较器输出锁存。这个方案能实现同样的效果但有两个代价。第一是占用 CPU 时间PWM 频率越高中断越频繁CPU 花在清锁存上的时间越多第二是存在延迟软件清除发生在中断里与 PWM 周期边界之间会有几微秒到十几微秒的延迟如果这个延迟内出现过一次过流事件保护响应时间会受影响。我实际测试时20kHz 的 PWM 下软件清除方案能正常工作过流触发也连续。但如果是 100kHz 以上的高频 PWM或者对保护响应时间要求苛刻的场景我更推荐用硬件同步清零。这也是芯片设计里加入这个同步机制的初衷——用它就该用到位。5.3 同类场景避坑与我的固定习惯把这次的教训扩散一下类似的“比较器 PWM”组合在很多场景都会踩坑不仅仅是过流保护。比如做 PWM 整流器或者逆变器的过零检测如果比较器输出配置成了锁存模式会出现“只检测到第一次过零后面全部丢失”的诡异现象。做电池放电曲线检测用比较器判断电压区间也会遇到类似问题。甚至在做 ADC 触发同步时如果比较器输出被锁存ADC 的注入采样触发也可能只在第一个周期执行一次。这些场景的共同点是比较器输出在功能上不仅要“告知状态”更要“产生边沿事件”。而锁存模式恰恰会吞掉后续边沿。所以在使用比较器前一定要搞清楚你这个应用需要的是“电平状态”还是“边沿事件”。需要持续电平判断的用直通模式需要故障自锁的用锁存模式需要在每个控制周期都能判断一次的用锁存加周期同步清零。最后聊一下我个人现在的固定做法拿到一颗新 MCU看到比较器输出配置的时候先想清楚“下一次触发从哪来”。如果答案里有“下一个 PWM 周期”那就要找到周期清零或者软件清除的路径并且写进配置。这个习惯来自这次踩坑也帮我避免过后续好几个项目里的同类问题。