Search code examples
cembeddedstm32

Timer 1 on STM32 not outputting onto GPIO Pin (Bluepill)


Using the Blue pill STM32F103 and libopencm3, I am using timer 1 to output a PWM signal onto PA8 and toggle the on board LED PC13. However this does not work. What have I done wrong in my code?

I can confirm that the timer is running at the correct frequency (scaled down to 24Hz) by toggling the LED in the interrupt. It is also counting to the correct value.

#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){}
}

Solution

  • If timer supports the break functionality (and TIM1 does), then OC/OCN outputs are disabled after the reset. To enable them, set the MOE bit in the TIMx_BDTR register. In the libopencm3 this is done by timer_enable_break_main_output function.

    enter image description here