3. 高级定时器互补PWM输出
任务目标
使用STM32高级定时器TIM1产生一对带死区时间的互补PWM信号(CH1与CH1N),用于驱动半桥电路中的上下桥臂MOSFET,防止直通短路。通过示波器或逻辑分析仪观察两路波形,验证死区时间与频率符合配置。
硬件与依赖
- 硬件:STM32F103系列开发板(如Mini板)、示波器或逻辑分析仪
- 软件:STM32CubeIDE或Keil MDK,STM32标准外设库或HAL库
- 引脚:TIM1_CH1(PA8)、TIM1_CH1N(PB13),需配置为复用推挽输出
核心实现
以下代码基于STM32标准外设库,完整实现TIM1互补PWM输出与死区配置。主频设为72MHz,输出频率20kHz,死区时间约1.08μs。
#include "stm32f10x.h"
void TIM1_ComplementaryPWM_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
// 1. 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_TIM1, ENABLE);
// 2. 配置PA8(TIM1_CH1)与PB13(TIM1_CH1N)为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 3. 时基配置:72MHz/(72-1+1)=1MHz计数频率,周期=50-1 → 20kHz
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 72分频 → 1MHz
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 49; // 50个计数 → 20kHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// 4. PWM模式1,占空比50%(25/50)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 使能互补输出
TIM_OCInitStructure.TIM_Pulse = 25;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// 5. 死区配置:DTG=108 → 死区时间 = 108 × 10ns ≈ 1.08μs
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Disable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Disable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 108;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// 6. 使能主输出MOE并启动定时器
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_Cmd(TIM1, ENABLE);
}
int main(void) {
TIM1_ComplementaryPWM_Init();
while (1) {
// 主循环无需额外处理,PWM由硬件持续输出
}
}
运行与验证
- 将代码编译下载至开发板,PA8与PB13分别连接示波器CH1与CH2通道,共地。
- 示波器设置为边沿触发,观察两路波形:CH1为高电平有效PWM,CH1N为反相PWM。
- 测量频率应为20kHz(周期50μs),占空比约50%。
- 放大上升沿/下降沿区域,测量CH1下降沿到CH1N上升沿之间的时间间隔,应约为1.08μs,即为死区时间。
- 判定通过条件:两路信号在任何时刻无同时为高的重叠区间,且死区时间与配置值误差在±0.2μs以内。
关键说明
- 高级定时器TIM1的互补输出必须使能主输出(TIM_CtrlPWMOutputs),否则引脚无波形。
- 死区时间由TIM_BDTR寄存器的DTG[7:0]位决定,本配置中DTG=108,对应死区时间 = 108 × TDTS,其中TDTS = 1/1MHz = 1μs,但实际死区计算为108 × 10ns = 1.08μs(因DTG[7:5]=011时,死区时间 = (64+DTG[4:0]) × 16 × TDTS,此处简化配置为直接映射模式)。若需精确计算,请参考参考手册DTG编码表。
- 若使用HAL库,对应函数为
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1)与HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1),死区通过sConfigDeadTime.DeadTime配置。