cancel
Showing results for 
Search instead for 
Did you mean: 

STM32f4 Disc kit, Reg'r Simultaneous DUAL ADC Mode, using DMA_Access Mode2

jagdish
Associate II
Posted on October 21, 2013 at 08:19

Hello everyone,

Kindly guide me to get this understand and resolve the following problem.

I am trying to work out following mode of ADC and DMA to suit my application. But the results are not as expected.

-Regular Simultaneous Dual ADC Mode

-DMA Access Mode 2

-ADC1 Ch14 and ADC2 Ch15 are used

My requirement is that ADC Ch14 and ADC Ch15  should be simultaneous converted and after the conversion of both ADC, their converted data should get stored via DMA in the 32-bit variable declared in software. This operation should be continuous.

For the above mentioned req, I have initialized ADC and DMA in following manner. but not getting the results. To confirm perfect working of the Hardware setup, I have tested the individual channels and  they are working fine. I have referred ref manual and some other documents and they state,

''

A 32-bit DMA transfer request is generated (if DMA[1:0] bits in the ADC_CCR register are equal to 0b10). This request transfers the ADC2 converted data stored in the upper half-word of the ADC_CDR 32-bit register to the SRAM and then the ADC1 converted data stored in the lower half-word of ADC_CCR to the SRAM

''

To which i understood that after conversion of ADC1 and ADC2, the data will be available in ADC_CDR register with ADC2 data in Higher 16-bit and ADC1 data in Lower 16-bit.

Pasting the ADC and DMA init routines.

#define ADC_CDR_ADDRESS         ((uint32_t)0x40012308)

u32 ADCDualConvertedValue = 0;

void DualModeADC_DMA_Config(void)

{

  ADC_CommonInitTypeDef ADC_CommonInitStructure;

  ADC_InitTypeDef ADC_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  DMA_InitTypeDef DMA_InitStructure;

  NVIC_InitTypeDef      NVIC_InitStructure;

 

  /* Enable peripheral clocks *************************************************/

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

   

  /* DMA2 Stream0 channel0 configuration **************************************/

  DMA_InitStructure.DMA_Channel = DMA_Channel_0;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCDualConvertedValue;

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS; //0x40012308

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = 1;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;        

  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);

  DMA_Cmd(DMA2_Stream0, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

 

  /* ADCs configuration ------------------------------------------------------*/

  /* Configure ADC Channel 14, 15 pin as analog input */

  /* ADC Channel 14 -> PC4 on ADC 1

     ADC Channel 15 -> PC5 on ADC 2

  */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; // CH14 (PC4) & CH15 (PC5)

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADC Common Init */

  ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC1 regular channels 14 configuration */

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 1;

  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channels 14 configuration */

  ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_3Cycles);

  /* Enable ADC1 DMA */

  ADC_DMACmd(ADC1, ENABLE);

 

  /* ADC2 regular channels 15 configuration */

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 1;

  ADC_Init(ADC2, &ADC_InitStructure);

  /* ADC2 regular channels 15 configuration */

  ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 1, ADC_SampleTime_3Cycles);

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

  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);

  /* Enable ADC1 */

  ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC2 */

  ADC_Cmd(ADC2, ENABLE);

  /* Start ADC1 Software Conversion */

  ADC_SoftwareStartConv(ADC1);

}// void DualModeADC_DMA_Config(void)

6 REPLIES 6
Posted on October 21, 2013 at 15:53

The target variable should be volatile, it is changed outside of normal program flow.

The 3 cycles for the conversion is going to generate some rough results.

The use of an IRQ here for one byte is crass. Consider how frequently the CPU is going to be hammered with this, and how many cycles the service routine will take.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jagdish
Associate II
Posted on October 23, 2013 at 14:33

Hi Clive,

Tx for the reply,

I tried changing following setting from enable to disable and it started working 

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

Additionally I have also done what you suggested and will keep it in the code.

Have another question regarding the ADC setting, please check if you can help me out.

We mention

ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

Can we reduce this or completely remove this delay ?

thanks,

Jagdish

Posted on October 23, 2013 at 16:46

Pretty sure that delay only relates to INTERLEAVE modes, ie where you are multiplexing the SAME input between multiple sample/hold circuits.

The normal conversion time is 3 + 12 cycles, where 3 is the SAMPLE time you program (charges R/C holding circuit), and 12 cycles for the conversion which you can't control.

The maximum ADCCLK is 36 MHz as I recall, or 2.4 MSps

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jagdish
Associate II
Posted on October 24, 2013 at 06:46

i.e. Since in my case, neither i am using interleaved mode, and nor i am sampling the same input signal, i can avoid that delay. I am ssampling 2 different input signals via 2 different channels and 2 different adc's. 

what shall i do to avoid this delay ?

please guide.

thanks.

Posted on October 24, 2013 at 13:53

What delay? I think I've already indicated this parameter is irrelevant in the mode being used.

The only way to increase the conversion rate is to use interleave mode, which effectively doubles the throughput by switching ADC during the conversion time.

Ok, So lets try this a different way, what conversion rate are you shooting for?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jagdish
Associate II
Posted on October 25, 2013 at 12:10

I want that both the adc conversion (ADC1 and ADC2) should get completed in 0.41usec (3 cycles + 12 cycles). As you mentioned that the 5 cycles delay is irrelevant in this dual mode regular simultaneous mode, then i got my answer. 

thanks a lot.