Skip to main content
HStee.1
Associate
July 12, 2022
Question

Can I measure PWM duty cycle using DMA?

  • July 12, 2022
  • 2 replies
  • 4577 views

I am on STM32F401 and I want to measure PWM duty cycle (PWM input) with timer 3 and a DMA channel. I'd like to have the DMA to do several measurements and then calculate the average over it. My configuration is like this:

0693W00000QKukTQAT.pngMy DMA config is like this:

0693W00000QKukdQAD.pngMy capture callback interrupt handler is:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

 uint8_t cnt;

 static volatile uint32_t PWM_ticks[PWM_input_buffer_size];

 static volatile uint32_t tick_value;

 // Get ticks differences

 for(cnt = PWM_input_buffer_size-1; cnt >= 1; cnt--)

 {

   if(PWM_input_buffer[cnt] > PWM_input_buffer[cnt-1])

   {

     PWM_ticks[cnt] = PWM_input_buffer[cnt] - PWM_input_buffer[cnt-1];

   }

   else // counter roll-over occurred

   {

     PWM_ticks[cnt] = PWM_input_buffer[cnt] + (htim3.Init.Period - PWM_input_buffer[cnt-1]);

   }

 }

 // Start PWM input via DMA - kick off next cycle

 if(HAL_TIM_IC_Start_DMA(&htim3, TIM_CHANNEL_2, PWM_input_buffer, PWM_input_buffer_size) != HAL_OK)

 {

     Error_Handler();

 }

}

When I put a breakpoint in that routine I see this in the watch window:

0693W00000QKukiQAD.pngTo the timer 3 channel 2 I have connected a 100Hz PWM signal with 30% duty cycle as a test signal. I use a clock of 84MHz and have set the clock divider to 84-1 so that one tick is 1us. In the watch window the signal is reflected by the ~7000 (low time) and ~3000 (high time) counts, this is because I've set the polarity selection to 'both edges'.

I am interested in the high time only (duty cycle %) but if I set polarity selection to Falling edge I get only numbers around 10000 which is the full period (100Hz) and I don't understand this. I would expect numbers around 3000 (high time of the signal).

I expect the trigger to start the measurement but obviously it does not work like that. Can anyone explain how it works and if it is possible at all to measure only duty cycle in this way? (i.e. which changes are needed)

On the internet I can find a lot about PWM generation using DMA but not so much on PWM input.. :(

This topic has been closed for replies.

2 replies

gbm
Lead III
July 12, 2022

If you capture only one of the edges, the interval will be always equal to the PWM period, no matter which edge you choose.

The timer has a special PWM measurement mode - maybe that's what you need - check the Reference Manual. I don't think the DMA is needed for this task.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
HStee.1
HStee.1Author
Associate
July 12, 2022

Yes, I just wanted to investigate if this is a possibility which can be used. If the DMA controller can do several measurements it can save a lot if IRQ's/context switching on the CPU. When the value is needed, let's say every 100ms (application cycle) one can simply calculate the average over the samples as provided by the DMA controller. I think that would be very neat.

Javier1
Principal
July 12, 2022

https://www.youtube.com/watch?v=qqzZ9C0umQ4

I used this tutrial and it works.

I measure frequencies in the order of Mhz and very precise dutycycles (microseconds)

hit me up in https://www.linkedin.com/in/javiermuñoz/