Skip to main content
Visitor II
May 10, 2025
Solved

STM32L011 TIM2 PWM no output

  • May 10, 2025
  • 7 replies
  • 738 views

Select PA1 as TIM2 CH2, those code are copy from ST official example(TIM21), and changed to TIM2.

STM32L09_0-1746884305122.png

no output from PA1, code as below:

void ConfigureTIM2AsPWM_EdgeAligned(void)
{
/* (1) Enable the peripheral clock of Timer x */
/* (2) Enable the peripheral clock of GPIOA */
/* (3) Select alternate function mode on GPIOA pin 1 */
/* (4) Select AF2 on PA1 in AFRH for TIM2_CH2 */

RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; /* (1) */
RCC->IOPENR |= RCC_IOPENR_GPIOAEN; /* (2) */
GPIOA->MODER |= 0X00000008; /* (3) */
GPIOA->AFR[0] |= 0X00000020; /* (4) */

/* (1) Set prescaler to 15, so APBCLK/16 i.e 1MHz */
/* (2) Set ARR = 8, as timer clock is 1MHz the period is 9 us */
/* (3) Set CCRx = 4, , the signal will be high during 4 us */
/* (4) Select PWM mode 1 on OC2 (OC2M = 110),
enable preload register on OC2 (OC2PE = 1) */
/* (5) Select active high polarity on OC2 (CC2P = 0, reset value),
enable the output on OC2 (CC2E = 1)*/
/* (6) Enable output (MOE = 1)*/
/* (7) Enable counter (CEN = 1)
select edge aligned mode (CMS = 00, reset value)
select direction as upcounter (DIR = 0, reset value) */
/* (8) Force update generation (UG = 1) */

TIM2->PSC = 15; /* (1) */
TIM2->ARR = 8; /* (2) */
TIM2->CCR1 = 4; /* (3) */
TIM2->CCMR1 |= TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE; /* (4) */
TIM2->CCER |= TIM_CCER_CC2E; /* (5) */
TIM2->CR1 |= TIM_CR1_CEN; /* (7) */
TIM2->EGR |= TIM_EGR_UG; /* (8) */
}

    This topic has been closed for replies.
    Best answer by waclawek.jan

    @STM32L09,

    > TIM2->CCR1 = 4; /* (3) */

    does not set TIM2_CH2 but TIM2_CH1. You would spot it yourself, would you print out and check the TIM2 registers content.

    JW

    7 replies

    Super User
    May 11, 2025

    The |= is wrong for MODER (and in general for AFR too). You need to set some bit(s) and clear other(s).

    A general pattern is 

    GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODE1_Msk) | (2 << GPIO_MODER_MODE1_Pos); // alternate mode

    or some macros wrapping that.

    hth

    KnarfB

     

    STM32L09Author
    Visitor II
    May 12, 2025

    thanks, KnarfB, I realize default value for MODE is 0XFFFF FFFF, so I should clear some bits.

    but seems still have other problems, still no PWM.

    Super User
    May 12, 2025

    Read out and check/post content of GPIO and TIM registers.

    Check given pin's connection by setting it as GPIO Output and toggling it "manually".

    JW

    STM32L09Author
    Visitor II
    May 12, 2025

    I use USART2 to print the register value, the value is HEX format.

    GPIOA->MODER:EBEBFCF9
    GPIOA->AFR[0]:20

    PA1 configuration is correct.

    Super User
    May 12, 2025

    Okay, and what about the TIM2 registers?

    And did you test the pin's connection as I recommended, by setting it to output and toggling in software?

    JW

    ST Employee
    May 12, 2025

    Hello,

    I have made an example code which is below. The code sets TIM2 to generate PWM on PA1. It comes from LL library so it can be reduced for your specific case, but it works right, I have tested it on my NUCLEO board.

     SET_BIT(RCC->APBENR1, RCC_APBENR1_TIM2EN); /* TIM2 clock enable */
     SET_BIT(RCC->IOPENR, RCC_IOPENR_GPIOAEN); /* GPIOA clock enable */
     MODIFY_REG(GPIOA->MODER, ((GPIO_PIN_1 * GPIO_PIN_1) * GPIO_MODER_MODE0), ((GPIO_PIN_1 * GPIO_PIN_1) * GPIO_MODER_MODE0_1)); /* Set PA5 pin mode to alternate function */
     MODIFY_REG(GPIOA->AFR[0], ((((GPIO_PIN_1 * GPIO_PIN_1) * GPIO_PIN_1) * GPIO_PIN_1) * GPIO_AFRL_AFSEL0),
     ((((GPIO_PIN_1 * GPIO_PIN_1) * GPIO_PIN_1) * GPIO_PIN_1) * 0x2U)); /* Set PA5 pin alternate function to AF2 */
     TIM2->PSC = 15; /* */
     TIM2->ARR = 199999; /* */
     TIM2->CCR2 = 99999; /* */
     MODIFY_REG(TIM2->CCMR1, (TIM_CCMR1_OC2M_Msk | TIM_CCMR1_OC2PE_Msk), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE)); /* Enable PWM1 mode, enable pre-load */
     TIM2->CCER |= TIM_CCER_CC2E; /* */
     TIM2->CR1 |= TIM_CR1_CEN; /* */
     TIM2->EGR |= TIM_EGR_UG; /* */
    Super User
    May 12, 2025

    Hi @Hl_st ,

    Can you please explain

    (GPIO_PIN_1 * GPIO_PIN_1)

     in setting GPIOA->MODER?

    Thanks,

    JW

    [EDIT] OK never mind, I see it now - if GPIO_PIN_N == 1 << N, this expression results in 1 << (2*N). Quite unusual nonetheless.

     

    Super User
    May 12, 2025

    @STM32L09,

    > TIM2->CCR1 = 4; /* (3) */

    does not set TIM2_CH2 but TIM2_CH1. You would spot it yourself, would you print out and check the TIM2 registers content.

    JW

    STM32L09Author
    Visitor II
    May 13, 2025

    Many thanks, it works now.