cancel
Showing results for 
Search instead for 
Did you mean: 

Sequence of ADC conversion in Regular Simultaneous Mode

ss2
Associate II
Posted on June 18, 2014 at 14:34

Hi Everyone

In my project, I need to capture 6 channel ADC signals in Regular Simultaneous Mode. for that, I just started for 2 channels (Channel 0 in ADC1 & Channel 1 in ADC2). Since it does simultaneous conversion, I gave the conversion sequence as 1,1 (i.e Rank for Ch0 is 1 & Ch1 is 1). It is working fine. But when i try it for 6 channels I'm getting problem, I'm not getting the actual signal, what I'm giving. I just confused with the sequence. For 6 channels i gave the sequence as (ADC1 Ch0 is 1 & ADC2 Ch1 is 1 ) (ADC1 Ch2 is 2 & ADC2 Ch3 is 2 ) (ADC1 Ch4 is 3 & ADC2 Ch5 is 3 ) is it right ???  can anyone help me... Please.

Part Number - STM32F103VDT7

Number of Samples - 256

Thank You...

Regards 

Selva

     

#adc-in-regular-simultaneous-mode
8 REPLIES 8
raptorhal2
Lead
Posted on June 18, 2014 at 16:48

Cancelled comment.

ss2
Associate II
Posted on June 19, 2014 at 06:55

Pardon..

raptorhal2
Lead
Posted on June 19, 2014 at 15:09

I believe the sequence is correct. And you are correctly not trying to sample the same channel simultaneously.

There may be a DMA setup problem. If you are still stuck, post the code.

Cheers, Hal

ss2
Associate II
Posted on June 21, 2014 at 12:34

Thank you for reply

/**************** GPIO Configuration ***********************/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

GPIO_Init(GPIOA,&GPIO_InitStructure);

/*************** DMA Configuration ******************/

DMA_InitTypeDef       DMA_InitStructure;

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

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* DMA1_Channel1 configuration **************************************/

DMA_DeInit(DMA1_Channel1);

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValues;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = 3;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_Init(DMA1_Channel1, &DMA_InitStructure);

/* DMA1_Channel1 enable */

DMA_Cmd(DMA1_Channel1, ENABLE);

/****************** ADC Configuration *******************/

  ADC_InitTypeDef       ADC_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

  

//  ADC_StartCalibration(ADC1);

//  while((ADC1->CR2&=0x04)==1);

//  ADC_StartCalibration(ADC2);

//  while((ADC2->CR2&=0x04)==1); 

  /* ADC1 Init ****************************************************************/

  ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ScanConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfChannel = 3;

  ADC_Init(ADC1, &ADC_InitStructure);

  ADC_Init(ADC2, &ADC_InitStructure);

  

  /* ADC1 regular channel configuration ******************************/

  ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1,  ADC_SampleTime_1Cycles5);

  ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 2,  ADC_SampleTime_1Cycles5);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3,  ADC_SampleTime_1Cycles5);

  ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 4,  ADC_SampleTime_1Cycles5);

  ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 5,  ADC_SampleTime_1Cycles5);

  ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 6,  ADC_SampleTime_1Cycles5); 

 

  /* Enable ADC1 DMA */

  ADC_DMACmd(ADC1, ENABLE);

  ADC_DMACmd(ADC2, ENABLE);

  

  ADC_Cmd(ADC1, ENABLE);

  ADC_Cmd(ADC2, ENABLE);

  

  /* Start ADC1 Software Conversion */

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);

  ADC_SoftwareStartConvCmd(ADC2, ENABLE);

/************** Timer 2 Configuration ****************/

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

TIM2->CNT  = 0x0000;

TIM2->PSC  = 0x0001;

TIM2->ARR  = 1406;     //1406=256 samples  //

TIM2->DIER = 0X0001;

TIM2->CR1  = 0x0085;

/**************** Timer 2 IRQ *******************/

void TIM2_IRQHandler(void)

volatile u16 ADC_1_Value = 0;

volatile u16 ADC_2_Value = 0;

if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==SET)

{

TIM_ClearFlag(TIM2,TIM_FLAG_Update);

*(ADC_Samples_ptr_CH_0_1 + fi_temp) = ADC_ConvertedValues[0];

*(ADC_Samples_ptr_CH_2_3 + fi_temp) = ADC_ConvertedValues[1];

*(ADC_Samples_ptr_CH_4_5 + fi_temp) = ADC_ConvertedValues[2];

fi_temp++;

if(fi_temp > 512)

 {

  fi_temp = 0;

TIM_Cmd(TIM2,DISABLE);

  ADC_Cmd(ADC1, DISABLE);

  ADC_Cmd(ADC2, DISABLE);

for(fi_temp=0;fi_temp<512;fi_temp++)

{

ADC1_Ch0_Samples[fi_temp]=ADC_Samples_arr_CH_0_1[fi_temp]&0xFFFF0000)>>16;

ADC2_Ch1_Samples[fi_temp] = (ADC_Samples_arr_CH_0_1[fi_temp]&0x0000FFFF);

ADC1_Ch2_Samples[fi_temp]=ADC_Samples_arr_CH_2_3[fi_temp]&0xFFFF0000)>>16;

 ADC2_Ch3_Samples[fi_temp] = (ADC_Samples_arr_CH_2_3[fi_temp]&0x0000FFFF);

ADC1_Ch4_Samples[fi_temp]=ADC_Samples_arr_CH_4_5[fi_temp]&0xFFFF0000)>>16;

ADC2_Ch5_Samples[fi_temp] = (ADC_Samples_arr_CH_4_5[fi_temp]&0x0000FFF

}

/*************** NVIC Configuration *****************/

void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStruct;

NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQChannel;  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStruct);

}

Posted on June 21, 2014 at 14:16

Is there a strong reason for not having a much bigger buffer, and interrupting on the DMA HT/TC? This would significantly reduce the interrupt loading.

The ADC must be configured as they would be individually, and then tied together

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 2, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 3, ADC_SampleTime_1Cycles5);
ADC_RegularChannelConfig(ADC2, ADC_Channel_5, 3, ADC_SampleTime_1Cycles5);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 21, 2014 at 14:23

Your code is also unnecessarily complex, why can't you just use the TIM to trigger the 6UP conversion when you need them (at desired period/frequency), get the DMA to do the whole sample buffering, and then interrupt you when it is done?

You might also want to review

STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\ADC\RegSimul_DualMode
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ss2
Associate II
Posted on June 25, 2014 at 09:01

Thanks Clive, Thank you for replay

Hi clive, as i told I'm capturing ADC Samples at 6 channels in regular simultaneous mode. So ADC1->DR will have both ADC1 & ADC2 data. 

ADC_Converteddata[0] = Ch1(ADC2) & Ch0(ADC1)

ADC_Converteddata[1] = Ch3(ADC2) & Ch2(ADC1)

ADC_Converteddata[2] = Ch5(ADC2) & Ch4(ADC1)

 And DMA is configured in Circular Mode. So respective channels value be stored at respective locations. As I'm giving input as 1KHz and want to take 256 samples, So approximately i need to take each samples at the interval of 4 micro second. Hence I selected ADC conversion time as 1.5 sampling cycle. is it possible ?? can i take 1.5 as sampling cycle ?? is it Overloaded ??.

I referred your link and I configured separately, now it's coming Thanks Clive.

In my program, I used DMA without interrupt and I'm taking ADC samples at Timer 2 IRQ with the interval of 4 micro second (Delay Time). I'm not using any external trigger, for start of conversion for that I'm using Software Trigger. 

My doubt is..

is their any better way to take 256 ADC samples of 1kHz ?? If so let me know please..

Thank you so much Clive..

Posted on June 25, 2014 at 12:48

Yes, you should be able to sample 6 channels at 1 KHz, the sample pairs will not occur at exactly the same time, ie pair 2 and 3 will be delayed by the sample+conversion time

Like I said you could make the buffer bigger, either x256 or x512, the former filling the buffer at the TC interrupt, or ping-pong halves at HT/TC interrupt. The latter is safer as the portion of the buffer you are working on won't be modified while the DMA fills the second half. You'd pace the ADC by using a 1 KHz timer trigger, and not using continuous mode.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..