Skip to main content
Associate
May 2, 2024
Solved

dynamically changing Timer ARR and CCR1

  • May 2, 2024
  • 1 reply
  • 2029 views

Hi everyone,

I am currently working on controlling a stepper motor using a PWM signal. I want to dynamically update the speed of the motor using different ARR and CCR1 values. Controlling the stepper works fine until an uncertain amount of time when the PWM signal appears to disappear completely.

 

I have read that something like enabling the preload register should help but this still doesn't fix my problem.

 

Here is my code so far:

 

#include "main.h"

#define C

#define F_CLK 24000000

uint16_t arr_from_freq(uint16_t freq){
 return F_CLK/(freq*(TIM2->PSC+1)) - 1;
}

int main(void){

 EPL_SystemClock_Config();

 // Enable the GPIOA and TIM2 peripherals
 RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

 // Set the mode of the GPIOA pin 5 to alternate function mode 2
 GPIOA->MODER |= GPIO_MODER_MODER5_1;
 GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5;
 GPIOA->AFR[0] |= 0b0010 << 20;
 
 // Disable the timer before setting the prescaler and overflow values
 TIM2->CR1 &= ~TIM_CR1_CEN;
 
 // Set the prescaler and overflow values
 TIM2->PSC = 3; // 10 seems to be optimal for now
 TIM2->ARR = 64000;
 TIM2->CCR1 = 0;

 // Set the PWM mode 1
 TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
 TIM2->CCMR1 |= TIM_CCMR1_OC1PE;
 // Set the output polarity to active high
 TIM2->CCER |= TIM_CCER_CC1E;

 // Enable the main output
 TIM2->BDTR |= TIM_BDTR_MOE;
 
 // Enbable the timer
 // Set the center-aligned mode 
 TIM2->CR1 |= TIM_CR1_CMS_0 | TIM_CR1_CEN;

 uint16_t lower_limit = 1000; // One rotation per minute because of step/8 microstepping
 uint16_t upper_limit = 3000;
 uint16_t pwm_frequency = lower_limit;
 uint16_t duty = arr_from_freq(lower_limit)/2;
 uint8_t state = 0;

 
 for(;;){
 if (pwm_frequency <= upper_limit && state == 0){
 pwm_frequency += 1;
 } else {state = 1;}

 if (pwm_frequency >= lower_limit && state == 1){
 pwm_frequency -= 1;
 } else {state = 0;}
 
 TIM2->ARR = arr_from_freq(pwm_frequency);
 duty = arr_from_freq(pwm_frequency)/2;
 TIM2->CCR1 = duty;
 delay(5000);
 }
}

 

 

Thanks in advance for anyone willing to help!

Cheers

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

 

Which STM32?

> I have read that something like enabling the preload register should help but this still doesn't fix my problem.

You mean setting TIMx_CR1.ARPE did not help?

Show how did you try. 

JW

PS TIM2 does not have BDTR.

 

1 reply

waclawek.jan
waclawek.janBest answer
Super User
May 2, 2024

 

Which STM32?

> I have read that something like enabling the preload register should help but this still doesn't fix my problem.

You mean setting TIMx_CR1.ARPE did not help?

Show how did you try. 

JW

PS TIM2 does not have BDTR.

 

SmarAuthor
Associate
May 2, 2024

Setting TIMx_CR1_ARPE did actually manage to fix this, I must have either tried the wrong register or just a completely wrong one. I am very new to programming on a low level basis, so thanks a lot for the quick and easy fix!