1. 项目概述
在嵌入式系统开发中,PWM(脉冲宽度调制)技术是控制电机、LED亮度等外设的核心技术之一。STM32系列微控制器内置了高级定时器,能够生成精确的PWM信号,并支持互补输出、死区插入和断路保护等高级功能。本实验基于STM32F4系列芯片,通过TIM8定时器实现主通道和互补通道的PWM输出,并加入断路保护和死区控制功能。
这个实验特别适合正在学习STM32高级定时器功能的开发者,或者需要在项目中实现电机控制、电源转换等应用的工程师。通过本实验,你将掌握:
- 如何配置STM32高级定时器的PWM输出
- 互补PWM信号的生成原理
- 死区时间的意义和配置方法
- 断路保护功能的实现
2. 硬件设计详解
2.1 引脚分配与连接
实验使用TIM8定时器的通道1(CH1)及其互补通道(CH1N)作为PWM输出引脚:
- 主输出通道:PC6(TIM8_CH1)
- 互补输出通道:PA5(TIM8_CH1N)
- 断路输入引脚:PA6(TIM8_BKIN)
硬件连接注意事项:
- 示波器通道1接PC6,通道2接PA5,两个探头的地线都要连接到开发板的GND
- PA6(断路输入)默认应接高电平(3.3V),当需要触发断路时接地
- 开发板上的KEY1和KEY2分别用于增加和减小PWM占空比
重要提示:STM32的GPIO引脚有复用功能映射,必须查阅芯片参考手册确认定时器通道对应的引脚。不同型号的STM32芯片,定时器通道的引脚映射可能不同。
2.2 时钟配置分析
TIM8作为高级定时器,挂载在APB2总线上。在STM32F4系列中,APB2的时钟频率通常为84MHz(当系统时钟为168MHz时)。定时器的实际时钟频率还受到预分频器的影响,计算公式为:
code复制定时器时钟 = APB2时钟 / (预分频值 + 1)
本实验中预分频值设置为1679,因此定时器时钟为:
code复制84MHz / 1680 = 50kHz
3. 软件实现解析
3.1 GPIO复用功能配置
STM32的GPIO可以配置为多种模式,当用作定时器输出时,需要设置为复用功能模式。关键配置步骤如下:
c复制static void TIMx_GPIO_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 开启GPIO时钟
RCC_AHB1PeriphClockCmd(ADVANCE_OCPWM_GPIO_CLK | ADVANCE_OCNPWM_GPIO_CLK | ADVANCE_BKIN_GPIO_CLK, ENABLE);
// 配置引脚复用功能
GPIO_PinAFConfig(ADVANCE_OCPWM_GPIO_PORT, ADVANCE_OCPWM_PINSOURCE, ADVANCE_OCPWM_AF);
GPIO_PinAFConfig(ADVANCE_OCNPWM_GPIO_PORT, ADVANCE_OCNPWM_PINSOURCE, ADVANCE_OCNPWM_AF);
GPIO_PinAFConfig(ADVANCE_BKIN_GPIO_PORT, ADVANCE_BKIN_PINSOURCE, ADVANCE_BKIN_AF);
// 配置GPIO参数
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用功能模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // 无上下拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 高速模式
// 应用配置到各个引脚
GPIO_InitStructure.GPIO_Pin = ADVANCE_OCPWM_PIN;
GPIO_Init(ADVANCE_OCPWM_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ADVANCE_OCNPWM_PIN;
GPIO_Init(ADVANCE_OCNPWM_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ADVANCE_BKIN_PIN;
GPIO_Init(ADVANCE_BKIN_GPIO_PORT, &GPIO_InitStructure);
}
3.2 定时器基础配置
TIM8的时基配置决定了PWM信号的频率和分辨率。关键参数包括:
- 预分频值(PSC):决定定时器时钟频率
- 自动重装载值(ARR):决定PWM周期
- 计数模式:通常使用向上计数模式
c复制TIM_TimeBaseStructure.TIM_Period = 1024-1; // PWM周期为1024个计数
TIM_TimeBaseStructure.TIM_Prescaler = 1680-1; // 预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // 重复计数器(高级定时器特有)
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
PWM频率计算公式:
code复制PWM频率 = 定时器时钟 / (ARR + 1)
= 50kHz / 1024 ≈ 48.8Hz
3.3 PWM输出模式配置
TIM8的通道1配置为PWM模式1,这是STM32中最常用的PWM模式。在PWM模式1下:
- 当计数器值小于CCR1时,输出有效电平(高电平)
- 当计数器值大于等于CCR1时,输出无效电平(低电平)
c复制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 = ChannelPulse; // 初始占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 主输出高电平有效
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; // 互补输出高电平有效
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);
3.4 死区与断路保护配置
死区时间是互补PWM输出中非常重要的参数,用于防止上下桥臂同时导通造成的短路。STM32内置了可编程的死区发生器,可以方便地插入死区时间。
c复制TIM_BDTRInitStructure.TIM_DeadTime = 11; // 死区时间
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; // 断路功能使能
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low; // 低电平触发断路
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);
死区时间的计算公式:
code复制死区时间 = DTG[7:0] × Tdtg
其中:
- 当DTG[7:5]=0xx时,Tdtg = Tdts
- 当DTG[7:5]=10x时,Tdtg = 2 × Tdts
- 当DTG[7:5]=110时,Tdtg = 8 × Tdts
- 当DTG[7:5]=111时,Tdtg = 16 × Tdts
Tdts = 定时器时钟周期 = 1/50kHz = 20μs
本实验中DTG=11(0x0B),属于第一种情况,因此:
code复制死区时间 = 11 × 20μs = 220μs
4. 关键功能实现
4.1 动态调整PWM占空比
通过按键可以动态调整PWM的占空比,这是通过修改CCR1寄存器的值实现的。CCR1的值决定了PWM脉冲的宽度。
c复制if(Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON) {
// 增大占空比
if(ChannelPulse<960)
ChannelPulse+=64;
else
ChannelPulse=1024;
TIM_SetCompare1(ADVANCE_TIM,ChannelPulse);
}
if(Key_Scan(KEY2_GPIO_PORT,KEY2_PIN) == KEY_ON) {
// 减小占空比
if(ChannelPulse>=64)
ChannelPulse-=64;
else
ChannelPulse=0;
TIM_SetCompare1(ADVANCE_TIM,ChannelPulse);
}
占空比计算公式:
code复制占空比 = CCR1 / (ARR + 1) × 100%
4.2 断路保护功能测试
断路保护是高级定时器的重要安全功能,当检测到故障信号时,会立即关闭所有PWM输出。测试方法:
- 将PA6(BKIN)引脚通过杜邦线连接到GND
- 观察示波器上的PWM输出应立即停止
- 重新将PA6接回高电平,PWM输出应恢复
5. 常见问题与调试技巧
5.1 PWM无输出排查步骤
-
检查时钟配置:
- 确认APB2时钟已使能(RCC_APB2PeriphClockCmd)
- 确认GPIO时钟已使能(RCC_AHB1PeriphClockCmd)
-
检查GPIO配置:
- 确认GPIO模式设置为AF(复用功能)
- 确认正确的复用功能映射(GPIO_PinAFConfig)
-
检查定时器配置:
- 确认TIM_Cmd已使能定时器
- 对于高级定时器,必须调用TIM_CtrlPWMOutputs使能PWM输出
-
检查PWM参数:
- 确认CCR1的值在0到ARR之间
- 确认TIM_OC1Init已正确调用
5.2 死区时间不生效的可能原因
- 没有调用TIM_BDTRConfig函数
- 没有使能TIM_BDTRInitStructure.TIM_AutomaticOutput
- 死区时间值设置过小,无法在示波器上观察到
- 互补输出没有使能(TIM_OutputNState_Enable)
5.3 示波器观测技巧
- 使用双通道同时观察主输出和互补输出
- 调整时间基准,使能观察到至少2-3个完整的PWM周期
- 使用触发功能稳定波形显示
- 测量死区时间时,使用光标功能精确测量两个边沿的时间差
6. 进阶应用建议
6.1 电机控制应用
本实验的互补PWM输出非常适合用于电机驱动,如:
- 三相无刷直流电机(BLDC)控制
- 步进电机细分驱动
- H桥驱动电路控制
在实际电机控制中,通常需要:
- 更高的PWM频率(10kHz-20kHz)
- 更精确的死区时间控制(根据功率器件特性调整)
- 加入电流检测和保护功能
6.2 电源转换应用
PWM也广泛应用于DC-DC转换器中,如:
- Buck降压转换器
- Boost升压转换器
- Buck-Boost升降压转换器
在这些应用中需要注意:
- PWM频率与电感、电容参数的匹配
- 最小导通时间的限制
- 输出电压的反馈调节
6.3 使用DMA自动更新PWM参数
对于需要频繁更新PWM参数的场景,可以使用DMA来减轻CPU负担:
- 配置DMA将内存中的参数自动传输到TIMx_CCR1寄存器
- 使用定时器更新事件触发DMA传输
- 构建PWM参数数组,实现复杂的PWM波形生成
通过这个实验,我们全面掌握了STM32高级定时器的PWM输出功能,包括互补输出、死区控制和断路保护等高级特性。这些知识在电机控制、电源管理等实际应用中非常重要。在实际项目中,还需要根据具体需求调整PWM频率、死区时间等参数,并加入适当的保护机制。