AnsweredAssumed Answered

ADC - EOC flag, DMA, overall conversion time

Question asked by gulin.marko on Jul 23, 2014
Latest reply on Aug 6, 2014 by Amel N
Dear all,

I have several questions regarding ADCs in STM32 (more specifically, I use STM32F407ZG). Let me explain you how I use them:

1) I have 3 ADCs that are triggered by the same timer (TIM4), and that are used in scan mode (each ADC has to "scan" 4 channels). All channels on all ADCs are configured to have the same sample time (56 cycles). Also, ADCs are configured to operate at 20 MHz via prescaler Div4 (APB2 operates at 84 MHz).

2) Timer that trigger all ADCs (TIM4) has a period of 991 us (confirmed by oscilloscope). Therefore, ADC on all 3 ADCs should start at the same time every 991 us.

3) I also use DMA (DMA2) to transfer converted values in memory, whereas I use one DMA2 stream for each ADC (Stream0 for ADC1, Stream1 for ADC3, Stream2 for ADC2).


1) I've recorded overall conversion time of a single ADC in following way: at each timer update interrupt is generated and PG3 (Pin 3 at GPIOG) is set to SET, and at each ADC EOC (end of conversion) interrupt is generated and PG3 is set to RESET. In this way I can record conversion time by oscilloscope. In datasheets, there is this formula for overall conversion time: Tconv=((sample time)+(12 cycles))/Fadc, whereas Fadc is 20 MHz, and the sample time is configured to be 56 cycles. Therefore, overall conversion time should be approximately 13.6 us, however oscilloscope showed that this is 26 us. Same thing happens when I use larger sample time (e.g. for 480 cycles) or larger prescaler (Div6 or Div8) - actual conversion time in both cases is almost twice as large as "theoretical" sample time. Also, I cannot use sample times smaller than 56 cycles (i.e. 3, 15 or 28 cycles) or smaller prescaler (i.e. Div2) - I don't know why, but ADC interrupt in these cases is never generated (PG3 is never set to RESET). Do you know why is this happening?

Worth to mention: I also tried in continuous scan mode (at the EOC new conversion starts immediately, i.e. ADCs are not triggered by timer). At each EOC interrupt is generated and PG3 is toggled in order to be able to measure the time with oscilloscope. In this mode, I can only use 480 cycles with Div4, and when I use Div8 I can set sample time to be 144 cycles (this is lowest possible). In all cases the overall conversion time is also twice as large as "theoretical" conversion time.

2) Since there is only one ADC interrupt handler, I want to check which ADC generated interrupt (in a case when I enable interrupts on all ADCs). However, simple check like ADC_GetITStatus(ADC1, ADC_IT_EOC)!=RESET also does not work, I dont know why, but the same thing for timer - TIM4 TIM_GetITStatus(TIM4, TIM_IT_Update)!=RESET -  works properly.

3) Considering DMA, I know that all 3 ADCs operate in parallel since they are triggered by the same source. However, there is only one DMA that can transfer data from ADCs to memory (DMA2). However, DMA2 has multiple streams, and the question is: Do all these streams also operate in parallel? Can I somehow configure DMA to generate interrupt when the "slowest" stream finishes with transfer?

Please find attached my main.c program. It is a bit big program (500+ lines of code), but there is nothing special in there, only configuration functions to configure RCC, GPIO, TIM, ADC, DMA and NVIC.