cancel
Showing results for 
Search instead for 
Did you mean: 

Can I measure PWM duty cycle using DMA?

HStee.1
Associate II

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.. :(

3 REPLIES 3
gbm
Lead III

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
Javier1
Principal

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)

we dont need to firmware by ourselves, lets talk

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.