cancel
Showing results for 
Search instead for 
Did you mean: 

timer DMA GPIO input capture with constant frequency

EvgenS Po
Associate II
Posted on May 09, 2018 at 08:37

Hello! I need to capture signals on inputs with constant frequency for further investigation. I use the following scheme: set timer frequency needed with update DMA request and capture size for DMA, then get data from input pins via DMA. The capture itself works. The problem is DMA capture inaccuracy, it seems DMA capture frequency floats and is not constant which results in input signal wrong capture. For exapmle, timer update frequency (capture frequency) is 100 kHz, input is10 kHz PWM signal with 50 % duty cycle; capture is 10,5 kHz PWM with 40 % - 55 % duty cycle. The more capturing frequency, the more capture inaccuracy. If timer update frequency is 1 MHz, input is10 kHz PWM signal with 50 % duty cycle; capture is 10,5 - 12,3 kHz PWM with 40 % - 55 % duty cycle. Please, see attached picture. I tried to sleep CPU while capturing, the result is the same.

What could be done to make capturing precise and stable?

#timer-update-dma-gpio

Note: this post was migrated and contained many threaded conversations, some content may be missing.
14 REPLIES 14
Posted on May 10, 2018 at 14:45

I'm capturing GPIOx->IDR. The picture shows captured signal on PA0, which should be of 50% duty cycle, but as it's seen, it's not.

Posted on May 11, 2018 at 10:09

I test the system as you suggested.

turn the DMA around and instead of inputting, output alternating data to a GPIO and observe those. That would give you information of how regularly or irregularly the DMA works.

The result is the same, output waveform is not as expected: pulses' duty cycle changes randomly and not uniform; but it should be 50 %.

Could you please take a look at code and point me out the error or suggest something to read about. I'm completely lost, any info would be appreciated.

Code for DMA driven by timer to capture GPIOx->IDR value.

//DMA def

&sharpdefine       DMA_FOR_CAPTURE                       DMA1

&sharpdefine       DMA_FOR_CAPTURE_ENR             AHBENR

&sharpdefine       DMA_FOR_CAPTURE_CLK_EN       RCC_AHBENR_DMAEN

&sharpdefine       DMA_CNL_FOR_CAPTURE              DMA1_Channel3

&sharpdefine       DMA_CNL_FOR_CAPTURE_IRQ      DMA1_Channel2_3_IRQn

//timer def

&sharpdefine       CAPTURE_TIMER                       TIM3

&sharpdefine       CAPTURE_TIMER_ENR             APB1ENR

&sharpdefine       CAPTURE_TIMER_CLK_EN      RCC_APB1ENR_TIM3EN

uint8_t Capture[1024];

  //DMA init

  RCC->DMA_FOR_CAPTURE_ENR |= DMA_FOR_CAPTURE_CLK_EN;

  DMA_CNL_FOR_CAPTURE->CPAR = (uint32_t) (&(GPIOA->IDR));

  DMA_CNL_FOR_CAPTURE->CMAR = (uint32_t)(Capture);

  DMA_CNL_FOR_CAPTURE->CNDTR = 1024;

  DMA_CNL_FOR_CAPTURE->CCR = DMA_CCR_MINC | DMA_CCR_TEIE | DMA_CCR_TCIE;     // | DMA_CCR_CIRC; tired circlular mode, without changes

  DMA_CNL_FOR_CAPTURE->CCR |= DMA_CCR_EN;

  NVIC_EnableIRQ(DMA_CNL_FOR_CAPTURE_IRQ);

  NVIC_SetPriority(DMA_CNL_FOR_CAPTURE_IRQ,0);

//timer init

  RCC->CAPTURE_TIMER_ENR |= CAPTURE_TIMER_CLK_EN;

  CAPTURE_TIMER->DIER = TIM_DIER_UDE;

  CAPTURE_TIMER->PSC = 23;

  CAPTURE_TIMER->ARR = 19;

CAPTURE_TIMER->CR1 |= TIM_CR1_CEN;

            

 __WFI();

//further processing and sending to PC

//-----------------------------------------------------

//DMA ISR

void DMA_FOR_CAPTURE_ISR(void)

{

  if ((DMA_FOR_CAPTURE->ISR & DMA_ISR_TCIF3) == DMA_ISR_TCIF3)

  {

    CAPTURE_TIMER->CR1 &= ~TIM_CR1_CEN;

    DMA_FOR_CAPTURE->IFCR |= DMA_IFCR_CGIF3;

    DMA_CNL_FOR_CAPTURE->CCR &= ~DMA_CCR_EN;

  }

}
Posted on May 11, 2018 at 13:11

The result is the same, output waveform is not as expected: pulses' duty cycle changes randomly and not uniform; but it should be 50 %.

Try to step back: forget about DMA for now and output PWM from the timer. Is it regular?

JW

PS. Skimming the above code, it looks OK. Is it the *only*software running on that mcu? No other timer/DMA?

Posted on May 11, 2018 at 14:38

'

The picture shows captured signal on PA0'

how? what's the mechanism in your code that ensures that PA0 flips with each capture event?

Posted on May 11, 2018 at 14:46

The

mechanism

is to capture GPIOx->IDR value with sample frequency 4-10 times higher than frequency of input signal, like oscilloscope does, but in my case input signal is digital.