Skip to main content
Associate II
January 21, 2026
Solved

PWM Generaion with udpate of the Period using DMA (STM32F411)

  • January 21, 2026
  • 1 reply
  • 206 views

Hi, I tried to find a solution in the forum, but unfortunately without success.
The problem is as follows: I need to generate a PWM signal that changes the period (not the duty cycle) with each iteration. (MCU: STM32F411)
I'm setting up the timer to use a PWM output on channel 1:

Semiory_0-1768983396786.png

Global interrupts are also active:

Semiory_3-1768984063378.png

 

Then the DMA will be configured to update the ARR register:

Semiory_1-1768983502826.png

In the code the DMA will be activated as following:

for (int i = 0; i < 32; i++)

{

u32FreqUpdate[i] = 2000 + i*100;

}


// Activate PWM channel 1:

TIM_CCxChannelCmd(htim4.Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
// Activate PWM output:

__HAL_TIM_MOE_ENABLE(&htim4);
// Activate ARR Update:
HAL_TIM_Base_Start_DMA(&htim4, u32FreqUpdate, sizeof(u32FreqUpdate)/sizeof(uint32_t));

As a result:

Semiory_2-1768983802474.png

The Output updates 3 times (without to change the frequency (period)) and then PWM Stops...

Could someone explain me, what I'm doing wrong?




Best answer by waclawek.jan

The way to debug this would be, as usually, reading out and checking the TIM and DMA registers content.

But let me guess.

u32FreqUpdate, that sounds as an array of 32-bit words; yet you've set the DMA to transfer 16-bit halfwords.

As the the first word in that array is 2000, its upper halfword is 0; DMA transfers that 0 into ARR which stops the timer. The 3 "successful" periods are due to ARR being preloaded (i.e. the first two periods are given by the initial setup) and the one nonzero halfword being transferred.

JW

PS. is u32FreqUpdate defined as a global array?

1 reply

waclawek.jan
waclawek.janBest answer
Super User
January 21, 2026

The way to debug this would be, as usually, reading out and checking the TIM and DMA registers content.

But let me guess.

u32FreqUpdate, that sounds as an array of 32-bit words; yet you've set the DMA to transfer 16-bit halfwords.

As the the first word in that array is 2000, its upper halfword is 0; DMA transfers that 0 into ARR which stops the timer. The 3 "successful" periods are due to ARR being preloaded (i.e. the first two periods are given by the initial setup) and the one nonzero halfword being transferred.

JW

PS. is u32FreqUpdate defined as a global array?

SemioryAuthor
Associate II
January 21, 2026

You are my Hero!
Switch to uint16_t has resolved the issue.