cancel
Showing results for 
Search instead for 
Did you mean: 

dynamically changing Timer ARR and CCR1

Smar
Associate II

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); } }
View more

 

 

Thanks in advance for anyone willing to help!

Cheers

1 ACCEPTED SOLUTION

Accepted Solutions
waclawek.jan
Super User

 

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.

 

View solution in original post

2 REPLIES 2
waclawek.jan
Super User

 

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.

 

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!