cancel
Showing results for 
Search instead for 
Did you mean: 

Changing PWM Mode during runtime

RuanSanchez
Associate II

Hello, I am trying to write a routine, that takes an array of structures as input and sets the timer 1 parameters. This function is called after each overflow of timer 1. I turn off the respective channels, then set the parameters, as seen in the following ISR:

 

void TIM1_UP_TIM16_IRQHandler(void)

{

htim1.Instance->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC1NE | TIM_CCER_CC2E | TIM_CCER_CC2NE | TIM_CCER_CC3E | TIM_CCER_CC3NE);

HAL_GPIO_WritePin(TIM1_UP_GPIO_Port, TIM1_UP_Pin, GPIO_PIN_SET);

HAL_TIM_IRQHandler(&htim1);

HAL_GPIO_WritePin(TIM1_UP_GPIO_Port, TIM1_UP_Pin, GPIO_PIN_RESET);

 

if (currentPattern < NUM_PATTERNS) {

setconfig(&durations[currentPattern]);

currentPattern++;

}

 

The setconfig function looks as follows:

:

void setconfig(TIM_SU const* const timersetup) {

// Function that takes a pointer to a TIM_SU structure as an argument

htim2.Instance->ARR = timersetup->tim2_period;

 

// Period of timer 1, i.e. the duration of the second pulse

htim1.Instance->ARR = timersetup->tim1_period;

 

// Duration of the first pulse (positive or negative)

htim1.Instance->CCR1 = timersetup->tim1_channel1_pwm_duration;

htim1.Instance->CCR2 = timersetup->tim1_channel2_pwm_duration;

htim1.Instance->CCR3 = timersetup->tim1_channel3_pwm_duration;

 

// Dead time, sets only the lower 8 bits (see page 1280)

htim1.Instance->BDTR &= ~TIM_BDTR_DTG; // Mask to clear the DTG bits

htim1.Instance->BDTR |= (uint32_t)(timersetup->dead_time & 0xFF);

 

htim1.Instance->CCMR1 &= ~TIM_CCMR1_OC1M; //channel 1 clearing

htim1.Instance->CCMR1 &= ~TIM_CCMR1_OC2M; //channel 2 clearing

htim1.Instance->CCMR2 &= ~TIM_CCMR2_OC3M; //channel 3 clearing

 

switch (timersetup->tim1_channel1_pwm_mode) {

case PWM_MODE_1:

TIM1->CCMR1 |= (TIM_OCMODE_PWM1 << TIM_CCMR1_OC1M_Pos);

break;

case PWM_MODE_2:

TIM1->CCMR1 |= (TIM_OCMODE_PWM2 << TIM_CCMR1_OC1M_Pos);

}

switch (timersetup->tim1_channel2_pwm_mode) {

case PWM_MODE_1:

TIM1->CCMR1 |= (TIM_OCMODE_PWM1 << TIM_CCMR1_OC2M_Pos);

break;

case PWM_MODE_2:

TIM1->CCMR1 |= (TIM_OCMODE_PWM2 << TIM_CCMR1_OC2M_Pos);

}

switch (timersetup->tim1_channel3_pwm_mode) {

case PWM_MODE_1:

TIM1->CCMR2 |= (TIM_OCMODE_PWM1 << TIM_CCMR2_OC3M_Pos);;

break;

case PWM_MODE_2:

TIM1->CCMR2 |= (TIM_OCMODE_PWM2 << TIM_CCMR2_OC3M_Pos);

}

}

Just as an example, one structure of the "durations" array:

 

TIM_SU durations[NUM_PATTERNS]= {

// Array of TIM_SU structures. NUM_PATTERNS defines the number of patterns. Each element is initialized with specific settings.

 

{

.tim2_period = 50000-1,

.tim1_channel1_pwm_duration =8000-1,

.tim1_channel2_pwm_duration =8000-1,

.tim1_channel3_pwm_duration =8000-1,

.tim1_period = 30000-1,

.dead_time = 200,

 

.tim1_channel1_pwm_mode = PWM_MODE_1,

.tim1_channel2_pwm_mode = PWM_MODE_1,

.tim1_channel3_pwm_mode = PWM_MODE_1,

 

},....

However, I am not able to change the PWM during runtime. I can change every other parameter with this code, the PWM Mode for each channel remains unchanged.

Is there any obvious reason I am missing? I turn the channels of, clear the respective bit-field and set it according to the desired PWM mode...

 

Thank you in advance for your help!

 

Ruan!

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> TIM1->CCMR1 |= (TIM_OCMODE_PWM1 << TIM_CCMR1_OC1M_Pos);

TIM_OCMODE_PWM1 is already shifted to the appropriate bits for the OC1M field within CCMR1. You're shifting it more, so other bits are being modified instead of what you want.

Definition:

 

#define TIM_OCMODE_PWM1                     (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1)                    /*!< PWM mode 1                             */

 

https://github.com/STMicroelectronics/stm32l4xx_hal_driver/blob/675fb52ad4d5e2b0ddd294487da6fb6d185f9868/Inc/stm32l4xx_hal_tim.h#L996

 

For channels 2 and 4, you will need to left-shift it by (TIM_CCMR1_OC2M_Pos - TIM_CCMR1_OC1M_Pos) bits.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

3 REPLIES 3
RuanSanchez
Associate II

I am using the STM32L433 Nucleo Board!

TDK
Guru

> TIM1->CCMR1 |= (TIM_OCMODE_PWM1 << TIM_CCMR1_OC1M_Pos);

TIM_OCMODE_PWM1 is already shifted to the appropriate bits for the OC1M field within CCMR1. You're shifting it more, so other bits are being modified instead of what you want.

Definition:

 

#define TIM_OCMODE_PWM1                     (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1)                    /*!< PWM mode 1                             */

 

https://github.com/STMicroelectronics/stm32l4xx_hal_driver/blob/675fb52ad4d5e2b0ddd294487da6fb6d185f9868/Inc/stm32l4xx_hal_tim.h#L996

 

For channels 2 and 4, you will need to left-shift it by (TIM_CCMR1_OC2M_Pos - TIM_CCMR1_OC1M_Pos) bits.

If you feel a post has answered your question, please click "Accept as Solution".
RuanSanchez
Associate II

Right, that did the trick!

 

Thank you TDK! 🙂