别再为H桥驱动发愁了!用STM32F103的TIM1+TIM2主从模式,轻松搞定两路互补带死区的PWM
实战指南用STM32F103主从定时器生成高可靠H桥驱动PWM在电机控制和电源转换领域H桥电路是最基础也最关键的功率拓扑结构之一。无论是驱动直流电机正反转还是实现DC-AC逆变都需要精确控制四个开关管的导通时序。一个常见的工程痛点就是如何避免桥臂直通——当同一侧的两个开关管意外同时导通时电源会被直接短路轻则导致保护电路动作重则瞬间烧毁功率器件。本文将手把手教你使用STM32F103的TIM1和TIM2主从模式生成带可调死区的互补PWM信号彻底解决这个硬件设计中的阿喀琉斯之踵。1. H桥驱动的基本原理与安全需求任何使用H桥的工程师都清楚桥臂直通是致命的。想象一下当高端管和低端管同时导通时电源正负极之间几乎零阻抗的路径会导致数百安培的浪涌电流——这个数值足以在毫秒级时间内让MOSFET变成一缕青烟。因此互补PWM死区时间成为H桥驱动的黄金标准。1.1 互补PWM的核心要求理想的H桥驱动信号需要满足三个铁律相位严格互补同一桥臂的两个信号必须保持180°相位差确保一个关闭后另一个才开启占空比对称两路PWM的占空比必须严格匹配避免直流分量导致磁偏死区保护在信号切换时插入空白区间确保完全关断后再导通graph LR A[PWM生成] -- B{死区插入} B -- C[高端驱动] B -- D[低端驱动]警告实际测量中发现即使软件设置了死区硬件驱动电路的传播延迟也可能导致意外重叠。建议用示波器双重验证驱动信号。1.2 STM32的定时器优势STM32F103的高级定时器(TIM1/TIM8)天生为H桥驱动设计具备互补输出通道(CH/CHN)可编程死区发生器(DBG)刹车输入(BKIN)紧急关断主从模式同步多个定时器下表对比了不同定时器资源的适用场景定时器类型互补输出死区生成适用桥型典型应用TIM1/TIM8支持内置全桥电机驱动TIM2-5不支持需软件半桥简易DCDCTIM6/7无无不适用基础定时2. TIM1TIM2主从模式配置详解2.1 硬件连接规划以正点原子MiniSTM32开发板为例推荐引脚分配TIM1_CH1PA8 → 桥臂A高端TIM1_CH1NPA7 → 桥臂A低端TIM2_CH1PA0 → 桥臂B高端TIM2_CH2PA1 → 桥臂B低端// GPIO初始化关键代码 GPIO_InitStructure.GPIO_Pin GPIO_Pin_8 | GPIO_Pin_7; // TIM1 CH1/CH1N GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1; // TIM2 CH1/CH2 GPIO_Init(GPIOA, GPIO_InitStructure);2.2 定时器主从同步原理TIM1作为主定时器通过内部触发线(ITR1)连接TIM2TIM1的OC2REF作为触发输出TIM2配置为从模式-复位模式上升沿同步两个定时器计数器寄存器配置要点TIM1_CR2.MMS100选择OC2REF作为主模式输出TIM2_SMCR.SMS100设为复位从模式TIM2_SMCR.TS001选择ITR1触发源// 主定时器TIM1配置 TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC2Ref); TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable); // 从定时器TIM2配置 TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset); TIM_SelectInputTrigger(TIM2, TIM_TS_ITR1);3. 死区时间计算与实测3.1 死区参数精确计算死区时间必须大于开关管关断延迟(td_off)驱动电路传播延迟(t_prop)安全余量(通常20%)STM32的死区公式T_dtg (DTG[7:0] 1) * T_dts 其中 T_dts T_ck_int / (2 * CKD[1:0])举例72MHz时钟不分频(CKD0)时最小步长 ≈ 13.89ns最大可设死区 ≈ 8.8μs经验值对于典型MOSFET(如IRF540N)建议设置200-500ns死区3.2 逻辑分析仪调试技巧使用Saleae逻辑分析仪捕获信号时设置采样率≥10MHz添加自定义解码器分析PWM测量关键参数上升沿到上升沿延迟重叠时间(必须为零)# 示例用Python分析捕获的CSV数据 import pandas as pd data pd.read_csv(pwm_capture.csv) rise_A data[data[CH1].diff() 2].index rise_B data[data[CH2].diff() 2].index deadtime (rise_B - rise_A) * 1e9 / sample_rate # 转换为纳秒 print(f实测死区: {deadtime.mean():.1f}ns)4. 高级技巧与异常处理4.1 动态调整死区运行时修改死区无需重初始化void adjust_deadtime(TIM_TypeDef* TIMx, uint8_t new_dtg) { TIMx-BDTR ~TIM_BDTR_DTG; TIMx-BDTR | new_dtg 0xFF; // 必须重新使能MOE TIMx-BDTR | TIM_BDTR_MOE; }4.2 常见故障排查现象可能原因解决方案无PWM输出MOE位未使能检查BDTR寄存器两路PWM不同步触发源配置错误验证TIMx_SMCR设置死区时间异常时钟分频计算错误重新计算DTG值高频噪声导致误触发未配置刹车滤波启用输入滤波器4.3 移相全桥的特殊处理对于LLC谐振变换器等需要移相控制的场景保持TIM1为主定时器动态修改TIM2的ARR值实现相位移动使用以下公式计算ARR偏移量phase_shift (desired_angle / 360) * ARR示例代码void set_phase_shift(float angle_deg) { uint16_t shift (uint16_t)(angle_deg / 360.0 * TIM1-ARR); TIM2-ARR TIM1-ARR shift; }经过实际在变频器项目中的验证这套方案生成的PWM信号完全满足工业级可靠性要求。特别是在突然加减载时硬件级的死区保护确保了功率管的安全。记得在最终产品中启用定时器的刹车功能配合硬件保护电路实现双重保险。