cancel
Showing results for 
Search instead for 
Did you mean: 

Collecting the ADC values from rising edge till the falling edge of the pulse

Sgowd.1
Associate II

I am using the DMA to collect the ADC data's. The ADC data's are now configured in a single mode and ADC is triggered at the rising edge of a pulse (I am using TIM8 for the pulse generation and the pulse can be set for 10us till 400us, i am also using the same TIM8 for rising edge ADC triggereing as well).

The conversion time of the ADC is approx 3us. So during the 10us pulse I approximatley get around 3 ADC values, so if i set the 10us pulse then the ADC value collection should stop at the falling edge of the pulse, so that i will have approx 3 ADC values for a 10us pulse.

So is it possible to configure the ADC in such a way that it should start at the rising edge of the pulse and should stop at the falling edge of the pulse.

NOTE:- The code is now working fine in a single mode triggering at the rising edge wherein only once the ADC value is captured irrespective of the pulse duration, but then in the continuous mode i want it to convert and collect the data from rising edge till the falling edge of the pulse and then stop the ADC

// this is my ADC and DMA initialization code.

void cADCReadout::initialize(sADCInitStruct init)

{

   m_sInitStruct = init;

   ADC_InitTypeDef      ADC_InitStructure;

   ADC_CommonInitTypeDef ADC_CommonInitStructure;

   DMA_InitTypeDef      DMA_InitStructure;

   //DMA

   DMA_InitStructure.DMA_Channel = init.DMAChannel;

   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(init.ADCChannel->DR);

   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(&m_aRecBuffer);

   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

   DMA_InitStructure.DMA_BufferSize = 0;

   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

   DMA_InitStructure.DMA_Priority = DMA_Priority_High;

   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

   DMA_Init(init.DMAStream, &DMA_InitStructure);

   DMA_Cmd(init.DMAStream, ENABLE);

   //ADC

   ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult;

   ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

   ADC_CommonInitStructure.ADC_DMAAccessMode =ADC_DMAAccessMode_1;

   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

   ADC_CommonInit(&ADC_CommonInitStructure);

   ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

   ADC_InitStructure.ADC_ScanConvMode = ENABLE;                       

   ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                        

   ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising ;  

   ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T8_TRGO;            

   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

   ADC_InitStructure.ADC_NbrOfConversion =1;

   ADC_Init(init.ADCChannel, &ADC_InitStructure);

   ADC_EOCOnEachRegularChannelCmd(init.ADCChannel, DISABLE);

   /* Enable DMA request after last transfer (Single-ADC mode) */

   ADC_DMARequestAfterLastTransferCmd(init.ADCChannel, ENABLE);

}

3 REPLIES 3
Danish1
Lead II

It should be possible to start a free-running timer when a digital input goes high. And have that timer trigger ADC conversions that are then stored in memory by DMA.

And it should also be possible to have a falling-edge-driven interrupt that stops the timer.

However I do not expect the HAL code to have routines that allow you to interrogate how many samples the DMA actually took - you'll probably have to read the Reference Manual on your stm32 and access the DMA registers yourself.

You might be able to avoid the need of a separate timer if you use the ADC_InitStructure.ADC_ContinuousConvMode (which maps to something documented in the Reference Manual).

What can go wrong?

Well suppose the rising edge happens a long time before the falling edge? How many samples do you capture before running out of memory in the buffer you allocated to capturing?

You only start taking samples once the input is digitally seen as high. This might mean you miss the start of the rising edge. (Back in the days of vacuum-tube oscilloscopes, the best of them had "delay lines" so the start of the edge-that-triggered-the-oscilloscope could be captured. I think modern digital oscilloscopes capture continuously but only bother to display from just-before the trigger pulse).

Hope this helps,

Danish

Thank you so much for the reply.

However, is it possible to the trigger the ADC conversion at the rising edge and stop the ADC conversions at the falling edge using the same timer?

(I know it can be triggered at the rising edge of the digital input which is working in my current code, however i am confused if it is able to stop the ADC conversions at the falling edge of the same pulse using the same timer). If it is possible, it would be really helpfull if you could let me know how exactly it can be done. I am not able to find a way to stop the ADC conversions using the same timer at the falling edge of the same pulse.

Read the reference manual for your stm32. The sections for each peripheral will show you what is possible without processor intervention.

If you want to do anything more clever/complicated than that, arrange for the event to interrupt the processor, and in your interrupt-service-routine do whatever needs doing. It won't happen as immediately as things done directly by hardware, but it generally is quite good enough.