ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

STM32 硬件过流保护实战:比较器直连 BKIN,纳秒级关断不靠软件

2026/9/3 15:43:53 拓冰建站 浏览量
STM32 硬件过流保护实战:比较器直连 BKIN,纳秒级关断不靠软件 烧掉第三对 MOS 管的那天下午我终于承认软件保护是靠不住的。当时的保护方案写得挺完整ADC 定时采母线电流超过阈值就在中断里调HAL_TIM_PWM_Stop()关掉六路输出。逻辑没问题测试也过了。但真正短路的时候从电流开始飙升到 MOS 管击穿整个过程只有几微秒而我的保护链路是定时器触发 ADC转换完成产生中断中断里读值比较比较超限调 HAL 函数关 PWM。这一圈跑下来至少十几微秒等软件反应过来管子已经冒烟了。后来才知道 STM32 上有一条完全不经过 CPU 的硬件保护通路比较器 COMP 的输出可以在芯片内部直连高级定时器的刹车输入 BKIN一旦触发PWM 输出在纳秒级被硬件强制关断不需要时钟、不需要中断、不需要代码执行。硬件保护通路长什么样采样电阻上的电压反映了母线电流。这个电压送到 COMP 的正输入端COMP 的负输入端接一个阈值电压两者一比较超限就翻转输出。关键在于 COMP 的输出去哪儿。传统做法是引到一个 GPIO再从 GPIO 绕回来接 TIM 的 BKIN 引脚。这样能用但多占两个引脚而且外部走线容易引入干扰。STM32 提供了内部直连COMP 的输出在芯片内部就接到了 TIM1/TIM8 的 BKIN 上不出芯片不占引脚。整条链路是采样电阻 → COMP 正输入 → COMP 内部比较 → COMP 输出 → 内部连线 → TIM BKIN → BDTR 逻辑 → 六路 PWM 全部关断这条链路里没有任何一环需要 CPU 参与。哪怕程序卡死在死循环里、哪怕时钟停了只要 COMP 供电正常保护依然生效。实测从采样电阻电压越限到 PWM 引脚变成安全电平延迟在 100ns 以内主要是 COMP 本身的传播延迟。对比一下软件保护ADC 采样周期加转换时间几微秒中断响应和函数调用几微秒累计十几微秒。硬件保护快了两个数量级。阈值怎么定COMP 的负输入反相输入可以选好几种源VREFINT内部参考电压约 1.2V或它的 1/4、1/2、3/4 分压DAC 输出这个最灵活阈值可以软件动态调整外部引脚用电阻分压给一个固定阈值用 DAC 做阈值是我最推荐的方案。因为不同工况下允许的电流上限不一样启动时允许大电流冲击稳态运行时阈值可以收紧。用 DAC 就能在运行中改阈值改一个寄存器的事。阈值电压的计算要从电流反推。假设采样电阻 5mΩ运放放大 20 倍允许峰值电流 30A采样电阻上的电压 30A × 5mΩ 150mV 运放输出 150mV × 20 3.0V所以 DAC 要输出 3.0V 作为阈值。12 位 DAC3.3V 满量程/* 阈值 3.0V - DAC 码值 */uint16_tdac_code(uint16_t)(3.0f/3.3f*4095);/* 3723 */HAL_DAC_SetValue(hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,dac_code);HAL_DAC_Start(hdac,DAC_CHANNEL_1);留出余量很重要。阈值卡在正常工作电流的边缘稍微有点纹波就误触发电机根本转不起来。我一般把阈值设在稳态峰值电流的 1.5 到 2 倍既能挡住真正的短路也不会被正常的换相尖峰打断。COMP 配置COMP_HandleTypeDef hcomp1;voidcomp_init(void){__HAL_RCC_COMP_CLK_ENABLE();hcomp1.InstanceCOMP1;hcomp1.Init.InputPlusCOMP_INPUT_PLUS_IO1;/* 采样信号引脚 */hcomp1.Init.InputMinusCOMP_INPUT_MINUS_DAC1_CH1;/* DAC 做阈值 */hcomp1.Init.OutputPolCOMP_OUTPUTPOL_NONINVERTED;hcomp1.Init.HysteresisCOMP_HYSTERESIS_MEDIUM;/* 滞回防抖 */hcomp1.Init.BlankingSrceCOMP_BLANKINGSRC_TIM1_OC5;/* 消隐窗口 */hcomp1.Init.ModeCOMP_POWERMODE_HIGHSPEED;/* 高速模式 */hcomp1.Init.TriggerModeCOMP_TRIGGERMODE_NONE;/* 不要中断 */HAL_COMP_Init(hcomp1);HAL_COMP_Start(hcomp1);}几个参数值得说清楚。Hysteresis 滞回必须开。采样信号上叠着开关噪声如果没有滞回信号在阈值附近抖动会让 COMP 输出疯狂翻转一次真实过流可能被解读成几十次触发。滞回给比较器加一个死区向上越过阈值才翻转要落回到阈值以下一定幅度才翻回来。中等档位一般够用。Blanking 消隐是这套方案的关键细节。MOS 管开通瞬间会有一个很大的电流尖峰反向恢复电流加寄生电容充电这个尖峰是正常的但幅度可能超过保护阈值。如果不做处理每次 PWM 上升沿都会误触发保护电机完全转不动。消隐的做法是用定时器的一个比较通道比如 TIM1_OC5生成一个窗口信号在这个窗口内 COMP 的输出被屏蔽。窗口时间设成开关尖峰的持续时间一般几百纳秒到一两微秒。这样开通瞬间的尖峰被忽略之后的真实过流照样能触发。Mode 功耗/速度模式选高速。低功耗模式下 COMP 的传播延迟能到几百纳秒甚至微秒级保护速度就打折扣了。这个外设本身耗电很少没必要在这里省。TriggerMode 不要开中断。硬件保护通路根本不需要中断COMP 触发后 BKIN 会直接关 PWM同时 TIM 会产生 Break 中断如果你使能了在那个中断里做善后处理记录故障、点故障灯、通知上层就行。COMP 自己的中断纯属多余。定时器侧的 BDTR 配置TIM1/TIM8 的 BDTR 寄存器控制刹车功能几个位必须配对TIM_BreakDeadTimeConfigTypeDef bdt{0};bdt.OffStateRunModeTIM_OSSR_ENABLE;bdt.OffStateIDLEModeTIM_OSSI_ENABLE;bdt.LockLevelTIM_LOCKLEVEL_1;bdt.DeadTime100;/* 死区时间 */bdt.BreakStateTIM_BREAK_ENABLE;/* BKE: 使能刹车 */bdt.BreakPolarityTIM_BREAKPOLARITY_HIGH;/* BKP: 高电平有效 */bdt.BreakFilter0x0F;/* 数字滤波 */bdt.AutomaticOutputTIM_AUTOMATICOUTPUT_DISABLE;/* AOE: 关键 */HAL_TIMEx_ConfigBreakDeadTime(htim1,bdt);/* 使能 Break 中断做善后 */__HAL_TIM_ENABLE_IT(htim1,TIM_IT_BREAK);AOEAutomatic Output Enable必须关掉。这个位如果置 1刹车条件消失后 PWM 输出会在下一个更新事件自动恢复。听起来很方便实际上非常危险短路可能是间歇性的自动恢复会让保护和短路交替发生管子在反复冲击下更容易炸。正确做法是保护触发后锁死必须软件确认故障已排除、显式调HAL_TIM_MspPostInit重新使能 MOE 才恢复输出。BreakPolarity 极性要和 COMP 输出极性对上。COMP 正常时输出低、过流时输出高那 BKP 就选高电平有效。搞反了的结果是正常运行时一直处于刹车状态PWM 根本输出不来你会以为定时器坏了。BreakFilter 数字滤波是 BKIN 侧的第二道防抖采样若干个时钟周期都确认有效才算触发。和 COMP 的滞回配合用误触发概率大幅降低。但滤波器会增加响应延迟每级大约几个定时器时钟周期所以别开满0x0F 那档大概几百纳秒可以接受。LockLevel 锁定级别是防止运行中被误改配置。Level 1 会锁住 BDTR 里的死区和刹车相关位写入被忽略。这个锁一旦设置只能靠复位解除量产固件建议开上开发阶段可以先不开。Break 中断里做什么硬件已经把 PWM 关了中断里只需要做善后voidHAL_TIMEx_BreakCallback(TIM_HandleTypeDef*htim){/* PWM 输出此时已被硬件关断MOE 位被清零 */g_fault_flagFAULT_OVERCURRENT;g_fault_count;/* 记录故障时刻的状态方便事后分析 */g_fault_snapshot.timestampHAL_GetTick();g_fault_snapshot.duty__HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1);g_fault_snapshot.speedg_current_speed;/* 关掉其他相关外设进入安全状态 */HAL_GPIO_WritePin(RELAY_GPIO_Port,RELAY_Pin,GPIO_PIN_RESET);led_fault_on();/* 不要在这里自动重启等上层确认 */}这个快照很有用。过流故障往往是间歇性的现场偶发一次事后没法复现。把触发时刻的占空比、转速、时间戳记下来多攒几次就能看出规律是启动瞬间炸的还是加速阶段炸的是同一个占空比附近还是随机。恢复输出要显式做而且要有条件inttry_recover_from_fault(void){if(g_fault_count3){return-1;/* 连续故障太多次拒绝恢复需要人工介入 */}/* 确认采样值已回到安全范围 */if(read_current_adc()SAFE_CURRENT_THRESHOLD){return-1;}/* 清故障标志重新使能主输出 */__HAL_TIM_CLEAR_FLAG(htim1,TIM_FLAG_BREAK);__HAL_TIM_MOE_ENABLE(htim1);g_fault_flagFAULT_NONE;return0;}软硬件双层保护才完整硬件保护快但它只能做一件事超过某个瞬时阈值就关断。判断不了电流没超峰值但持续偏高这种慢性过载。所以合理的方案是两层硬件层COMP BKIN阈值设在绝对不能超的位置比如 MOS 管额定电流的 80%处理短路、堵转、驱动电路故障这类灾难性事件纳秒级响应。软件层ADC 定时判断阈值设得低一些加上时间维度判断。比如电流超过额定值 1.2 倍持续 500ms就降额或停机这属于热保护范畴慢一点没关系。两层的阈值要留出足够间隔不然软件层还没来得及动作硬件层就跳了等于软件层白写。我一般硬件阈值设在软件阈值的 1.5 倍以上。十个坑一、BKP 极性配反。正常运行时就处于刹车状态PWM 一点输出都没有。查 BDTR 的 BKP 位和 COMP 输出极性是否匹配。二、AOE 开着导致反复冲击。刹车条件消失后自动恢复短路间歇发生就变成反复冲击 MOS 管比不保护更危险。量产固件必须关 AOE。三、没配 Blanking开关尖峰误触发。每个 PWM 上升沿都触发保护电机完全转不起来。用定时器 OC 通道生成消隐窗口屏蔽开通瞬间几百纳秒。四、没开滞回一次过流触发几十次。COMP 输出在阈值附近疯狂翻转。开 Hysteresis中等档位起步。五、COMP 用了低功耗模式。传播延迟从纳秒变微秒保护速度打折扣。功率场合固定用高速模式。六、阈值算错把运放增益漏了。直接用采样电阻上的电压当阈值忘了后面还有 20 倍放大结果阈值差 20 倍等于没保护。七、阈值定得太紧被正常电流触发。启动冲击电流可能是稳态的好几倍阈值贴着稳态电流设肯定误触发。留 1.5 到 2 倍余量。八、Break 中断里试图重启 PWM。中断里立刻恢复输出如果故障还在就是无限循环触发。恢复逻辑放主循环加故障计数上限和电流确认。九、只做硬件保护不做软件保护。硬件挡不住慢性过载和过温长时间偏高电流会把管子热死。两层配合才完整。十、LockLevel 在开发阶段就开满。锁了之后改不了配置又只能靠复位解除调试很痛苦。开发用 OFF量产再开 Level 1。一个可以照抄的初始化顺序顺序很重要配错顺序会出现保护配好了但没生效或者一上电就跳保护。voidmotor_protect_init(void){/* 1. 先启 DAC 给出阈值保证 COMP 有正确的参考 */dac_threshold_init(3723);/* 3.0V, 对应 30A *//* 2. 再配 COMP此时阈值已稳定 */comp_init();/* 滞回 消隐 高速 *//* 3. 配定时器 PWM还不使能输出 */MX_TIM1_Init();/* 4. 配 BDTR死区 刹车 关 AOE */tim1_bdtr_config();/* 5. 清一次可能存在的 Break 标志 */__HAL_TIM_CLEAR_FLAG(htim1,TIM_FLAG_BREAK);/* 6. 最后使能 PWM 输出和主输出 */HAL_TIM_PWM_Start(htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(htim1,TIM_CHANNEL_1);__HAL_TIM_MOE_ENABLE(htim1);}先给阈值再启比较器是为了避免 COMP 在阈值还是 0V 的时候就判定过流把 Break 标志置上。第 5 步清标志是补救万一前面还是抖了一下这里清掉再使能输出就不会一上电就跳保护。小结从烧管子到搞明白这套硬件保护我花了大概两周。真正的转折点是意识到一件事软件永远追不上功率器件的失效速度。代码执行需要时钟、需要取指、需要中断响应加起来是微秒级MOS 管从过流到击穿是几微秒。这两个时间尺度是重叠的靠软件抢时间本身就是个赌博。COMP 直连 BKIN 这条通路把保护从软件时间尺度拉到了硬件时间尺度赌局才变成了确定性。配置这套东西大概两百行代码一个下午能调通。相比一对 MOS 管的成本和炸管的排查时间这笔投入太值了。保护逻辑写在中断里等于把安全托付给了调度延迟写在 BDTR 里才是真的托付给了硬件。