STM32蓝板(Bluepill) Timer1无法输出PWM至GPIO引脚问题排查
STM32F103 Bluepill Timer1 PWM输出异常排查(libopencm3)
问题描述
使用STM32F103蓝板(Bluepill)搭配libopencm3库,尝试通过Timer1在PA8引脚输出PWM信号,同时利用定时器比较中断触发板载LED(PC13)翻转。目前中断功能正常(LED按预期24Hz翻转,计数数值符合预期),但PA8的PWM信号未正常输出,附代码如下:
#include <stdlib.h> #include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #include <libopencm3/usb/usbd.h> #include <libopencm3/usb/cdc.h> #include <libopencm3/stm32/timer.h> #include <libopencm3/cm3/nvic.h> void tim1_cc_isr(){ timer_clear_flag(TIM1, TIM_SR_CC1IF); gpio_toggle(GPIOC, GPIO13); } int main(void) { unsigned int i; // Initialize the master clock rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOC); gpio_set(GPIOC, GPIO13); gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); // Timer clocks rcc_periph_clock_enable(RCC_AFIO); rcc_periph_clock_enable(RCC_TIM1); timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_CENTER_1, TIM_CR1_DIR_UP); timer_enable_oc_output(TIM1, TIM_OC1); timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); timer_set_oc_polarity_low(TIM1, TIM_OC1); gpio_set_mode(GPIO_BANK_TIM1_CH1, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM1_CH1); // Set Period timer_set_prescaler(TIM1, 1000); // Count to 750 for 24Hz timer_set_period(TIM1, 750); timer_clear_flag(TIM1, TIM_SR_CC1IF); timer_set_oc_value(TIM1, TIM_OC1, 350); timer_enable_counter(TIM1); nvic_enable_irq(NVIC_TIM1_CC_IRQ); timer_enable_irq(TIM1, TIM_DIER_CC1IE); while(1){} }
问题排查与修复方案
- 高级定时器主输出未使能:STM32F1的高级定时器(TIM1)默认关闭主输出,即使配置了通道OC输出,不开启主输出引脚不会有PWM信号。必须添加:
timer_enable_break_main_output(TIM1); - GPIO速率不匹配:系统时钟为72MHz,PA8作为TIM1_CH1输出,建议将GPIO速率提升至
GPIO_MODE_OUTPUT_10_MHZ,避免信号失真。 - 定时器模式冲突:你同时设置了中心对齐模式(
TIM_CR1_CMS_CENTER_1)和向上计数(TIM_CR1_DIR_UP),中心对齐模式下计数方向会自动切换,无需手动指定向上计数,可改为边沿对齐模式(TIM_CR1_CMS_EDGE)或保留中心对齐但移除TIM_CR1_DIR_UP参数。 - 预分频器计算错误:当前预分频器设置为1000时,实际频率与预期24Hz不符。正确计算:72MHz / (PSC+1) / (ARR+1) =24Hz → (PSC+1)*(ARR+1)=3e6。若ARR设为749(周期750),则PSC需设为3999。
修改后的完整代码
#include <stdlib.h> #include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/timer.h> #include <libopencm3/cm3/nvic.h> void tim1_cc_isr(){ timer_clear_flag(TIM1, TIM_SR_CC1IF); gpio_toggle(GPIOC, GPIO13); } int main(void) { // Initialize the master clock rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOC); gpio_set(GPIOC, GPIO13); gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); // Timer clocks rcc_periph_clock_enable(RCC_AFIO); rcc_periph_clock_enable(RCC_TIM1); // 使用边沿对齐模式,避免方向设置冲突 timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); timer_enable_oc_output(TIM1, TIM_OC1); timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); timer_set_oc_polarity_low(TIM1, TIM_OC1); // 提升GPIO输出速率 gpio_set_mode(GPIO_BANK_TIM1_CH1, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_TIM1_CH1); // 修正预分频器与周期,确保24Hz频率 timer_set_prescaler(TIM1, 3999); timer_set_period(TIM1, 749); timer_clear_flag(TIM1, TIM_SR_CC1IF); timer_set_oc_value(TIM1, TIM_OC1, 350); // 开启TIM1主输出(高级定时器必需) timer_enable_break_main_output(TIM1); timer_enable_counter(TIM1); nvic_enable_irq(NVIC_TIM1_CC_IRQ); timer_enable_irq(TIM1, TIM_DIER_CC1IE); while(1){} }
内容的提问来源于stack exchange,提问作者EdL
相关产品推荐
相关产品推荐

