Skip to main content
Associate III
May 10, 2025
Solved

STM32L011 TIM2 PWM no output

  • May 10, 2025
  • 7 replies
  • 3104 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) */
}

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

KnarfB
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
Associate III
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.

waclawek.jan
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
Associate III
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.

waclawek.jan
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; /* */
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
waclawek.jan
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.

 

waclawek.jan
waclawek.janBest answer
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
Associate III
May 13, 2025

Many thanks, it works now.