2018-05-08 11:37 PM
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.2018-05-10 07:45 AM
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.
2018-05-11 03:09 AM
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_TIM3ENuint8_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; }}2018-05-11 06:11 AM
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?
2018-05-11 07:38 AM
'
The picture shows captured signal on PA0'
how? what's the mechanism in your code that ensures that PA0 flips with each capture event?
2018-05-11 07:46 AM
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.