cancel
Showing results for 
Search instead for 
Did you mean: 

PWM problems

Petrarka
Associate II

Hello! Recently I got into STM programming for my internship and I cannot figure out register level programming yet, I have this piece of code 

```

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_APB1ENR_TIM2EN;
GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;

TIM2->CCER|=TIM_CCER_CC1E;
TIM2->CR1 |=TIM_CR1_ARPE;
TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;

TIM2->PSC=42; //trivial
TIM2->ARR=1000; //trivial values
TIM2->CCR1=250; //trivial

TIM2->EGR |=TIM_EGR_UG;
TIM2->CR1 |=TIM_CR1_CEN;
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{


/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
```
Which in theory, to me, looks like it should work, however there are things I still do not fully understand, for example: Here I wanted to use Tim2 on channel 1 because I can use that on my PA5 pin which is LED2 on my Nucleo f401RE board, and I wanted to produce a PWM signal on it, however, it just doesn't display, if someone could provide some feedback or guidance it would be greatly appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions

This is the final code that worked, thank you for your help Jan

  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  GPIOA->MODER |= ( 0x2UL << GPIO_MODER_MODE5_Pos); //alternate mode
  GPIOA->AFR[0]|= 0x000100000;//alternate function for port A 5
  TIM2->PSC = 840 - 1;     // Set prescaler
  TIM2->ARR = 1000;         // Set auto-reload
  TIM2->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );
  TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
  TIM2->CR1 |= TIM_CR1_ARPE|TIM_CR1_CEN|TIM_CR1_URS;
  TIM2->CCER &= ~TIM_CCER_CC1P;
  TIM2->CCER |= TIM_CCER_CC1E;
  TIM2->EGR |= TIM_EGR_UG;
  TIM2->DIER |= ( TIM_DIER_CC1IE | TIM_DIER_UIE );
  TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );

View solution in original post

5 REPLIES 5

> GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;

What does this do?

You may need to set TIMx_AFR[] too, see AF assignment table in the Datasheet.

> TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;

What does this do? 

JW

Doesn't 

> GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;
Set my pins mode to Alternate function? I am playing with Pin A 5 so... I figured id need to configure Mode5 to 10
TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;
Sets my Timer's mode to PWM1, according to the data sheet pwm 1 is "110" in the OC bits, and OC1PE is for preloading the register but im not really sure what that is.

Updated the code to this, still doesnt work 

RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  GPIOA->MODER |= ( 0x2UL << GPIO_MODER_MODE5_Pos); //alternate mode
  GPIOA->AFR[0]|= 0x000000010;//alternate function for port A 5
  TIM2->PSC = 840 - 1;     // Set prescaler
  TIM2->ARR = 1000;         // Set auto-reload
  TIM2->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );
  TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
  TIM2->CR1 |= TIM_CR1_ARPE;
  TIM2->CCER &= ~TIM_CCER_CC1P;
  TIM2->CCER |= TIM_CCER_CC1E;
  TIM2->CR1 |= TIM_CR1_URS;
  TIM2->EGR |= TIM_EGR_UG;
  TIM2->DIER |= ( TIM_DIER_CC1IE | TIM_DIER_UIE );
  TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );

> Doesn't 

>> GPIOA->MODER |=GPIO_MODER_MODE5_1 | GPIO_MODER_MODE5_0;
> Set my pins mode to Alternate function? I am playing with Pin A 5 so... I figured id need to configure Mode5 to 10

Yes, but that code sets MODE5 to 0b11.

> TIM2->CCMR1 |=TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_0|TIM_CCMR1_OC1PE;
> Sets my Timer's mode to PWM1, according to the data sheet pwm 1 is "110" in the OC bits,

That sets mode to 0b011 (and sets the 1st bit twice).

Reading code - including one's own - is an equally important skill as writing it.

>and OC1PE is for
> preloading the register but im not really sure what that is.

If you set TIMx_CCR1 preloading, the value you write into TIMx_CCR1 does not get active immediately, but only after the next Update event.

 

> Updated the code to this, still doesnt work

> GPIOA->AFR[0]|= 0x000000010;//alternate function for port A 5

That's not value for PA5 but for PA1. There are 4 bits per pin in that register.

 

> TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );

This is not the source of problem here, but generally, don't use RMW to clear TIMx_SR bits.

JW

 

This is the final code that worked, thank you for your help Jan

  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  GPIOA->MODER |= ( 0x2UL << GPIO_MODER_MODE5_Pos); //alternate mode
  GPIOA->AFR[0]|= 0x000100000;//alternate function for port A 5
  TIM2->PSC = 840 - 1;     // Set prescaler
  TIM2->ARR = 1000;         // Set auto-reload
  TIM2->CCMR1 |= ( 0x6UL << TIM_CCMR1_OC1M_Pos );
  TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
  TIM2->CR1 |= TIM_CR1_ARPE|TIM_CR1_CEN|TIM_CR1_URS;
  TIM2->CCER &= ~TIM_CCER_CC1P;
  TIM2->CCER |= TIM_CCER_CC1E;
  TIM2->EGR |= TIM_EGR_UG;
  TIM2->DIER |= ( TIM_DIER_CC1IE | TIM_DIER_UIE );
  TIM2->SR &= ~( TIM_SR_CC1IF | TIM_SR_UIF );