cancel
Showing results for 
Search instead for 
Did you mean: 

PWM, dynamically changing period, duty cycle (directly or via DMA)

Hatte
Associate II

Below question relates to STM32F0 and STM32F1 series MCU's.

From the documentation (HAL), I have been unable to determine, whether or not on-the-fly changes are supported to the PWM period (TIM_TimeBaseInitTypeDef.TIM_Prescaler) and/or duty cycle (directly via CCR1 or via DMA: DMA_InitTypeDef.DMA_Memory0BaseAddr).

Other than whether or not on-the-fly changes (to a running PWM-configured timer) are supported, I am also interested in knowing when on-the-fly changes takes effect (immediate, at next timer cycle, ...)?

  1. When changing the address of a (circular) DMA memory buffer containing PWM duty cycle values, will it take effect immediately, or when the current (memory) cycle has been completed. I would prefer to be able to work with a double buffered DMA design, where the DMA buffer takes effect when the current cycle completes. Alternatively, I could rely on an interrupt when the cycle completes, and update the DMA buffer then.
  2. When changing the PWM duty cycle directly via CCR1, will this change take effect immediately, or at the end of a timer cycle.
  3. When changing the PWM period/frequency (via TIM_TimeBaseInitTypeDef.TIM_Prescaler) on a running PWM configured timer, will this change take effect immediately, or at the end of a cycle.

Any help and/or references to existing documentation or examples will be greatly appreciated.

/Morten

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

The prescaler PSC always uses the shadow register, changes take effect after the next update event (timer overflow or TIM_EGR_UG).

The period ARR uses the shadow register when TIM_CR1_ARPE = 1, otherwise changes take effect immediately.

The compare register CCRx uses the shadow only when OCxPE = 1.

Note that though the period will be changed when you change PSC, the duty cycle will be determined by the CCRx/ARR ratio.

DMA address can't be changed whlie running, but you can request a DMA interrupt when half of the buffer is processed, so you'd always know which half of the buffer is currently active. You can also read the number of data words remaining in the buffer from the DMA transfer counter,

Read AN4776 Application note General-purpose timer cookbook for STM32 microcontrollers if you haven't read it before.

View solution in original post

6 REPLIES 6
TDK
Guru

1

Dma address cant be changed while active. It takes effect immediately the next time you start the dma. You could use double buffer mode.

2

The behavior can be either based on the value of the OC1PE bit. It can either be immediately or updated on the update event. Take a look at this field definition in the reference manual.

With DMA, the behavior is the same as if you change it manually, although dma can be delayed if you have a lot going on.

3

For the prescaler, I believe this is updated immediately. I dont believe it uses a shadow register.

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

Thanks for your advise. I conclude, that ...

  1. Changing the DMA address requires a disable/enable DMA cycle?
  2. Double buffering would require using the Shadow/Preload register?
  3. In that case, I would choose to update the prescaler when the UpdateEvent interrupt occurs, which would be the most predictable transition of PWM-period.

1 Yes
3 For the most predictability, I would leave the prescaler alone and only adjust the CCMR register to adjust the duty cycle. This may require avoiding the HAL drivers and working with registers directly. I’m not sure what HAL offers in this capacity.
If you feel a post has answered your question, please click "Accept as Solution".
I meant CCRx, not CCMR.
If you feel a post has answered your question, please click "Accept as Solution".
berendi
Principal

The prescaler PSC always uses the shadow register, changes take effect after the next update event (timer overflow or TIM_EGR_UG).

The period ARR uses the shadow register when TIM_CR1_ARPE = 1, otherwise changes take effect immediately.

The compare register CCRx uses the shadow only when OCxPE = 1.

Note that though the period will be changed when you change PSC, the duty cycle will be determined by the CCRx/ARR ratio.

DMA address can't be changed whlie running, but you can request a DMA interrupt when half of the buffer is processed, so you'd always know which half of the buffer is currently active. You can also read the number of data words remaining in the buffer from the DMA transfer counter,

Read AN4776 Application note General-purpose timer cookbook for STM32 microcontrollers if you haven't read it before.

A belated "thank you"​ for your comprehensive and accurate answer. Much appreciated!