AnsweredAssumed Answered

DMA problem is using ADC1 scan mode

Question asked by keshavarz.abbas on Dec 4, 2014
Latest reply on Dec 10, 2014 by keshavarz.abbas
hello guys

I am using stm32f103RET
I want to use ADC1 in scan mode
I do software start conversion in a timer interrupt and I configured DMA to save conversion values to a memory buffer
my configuration code is here
void Volumes_init(uint32_t *volume_buff) // tuning for 0.1 sec interval interruption
{
     TIM_TimeBaseInitTypeDef      TIM_InitStruct;
  ADC_InitTypeDef     ADC_InitStructure;
  NVIC_InitTypeDef           NVIC_InitStruct;
  GPIO_InitTypeDef           GPIO_InitStructure;
     DMA_InitTypeDef           DMA_InitStructure;
     // Configure ADC_INPUT_PIN as analog input ------------------------------------
     VOLUMES_GPIO_RCC_INIT();
     GPIO_StructInit( &GPIO_InitStructure );
  GPIO_InitStructure.GPIO_Pin = VOLUME1_GPIO_PIN; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     
  GPIO_Init( VOLUME1_GPIO, &GPIO_InitStructure );
  GPIO_InitStructure.GPIO_Pin = VOLUME2_GPIO_PIN; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     
  GPIO_Init( VOLUME2_GPIO, &GPIO_InitStructure );
  GPIO_InitStructure.GPIO_Pin = VOLUME3_GPIO_PIN; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;     
  GPIO_Init( VOLUME3_GPIO, &GPIO_InitStructure );


  GPIO_InitStructure.GPIO_Pin = SENSORS_GND_GPIO_PIN; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;     
  GPIO_Init( SENSORS_GND_GPIO, &GPIO_InitStructure );
     // ADC configuration ----------------------------------------------------------
     VOLUMES_ADC_RCC_INIT();
     RCC_ADCCLKConfig( RCC_PCLK2_Div6 ); // 72MHz / 6 = 12MHz // must not exceed 14MHz
     ADC_InitStructure.ADC_Mode =  ADC_Mode_Independent;
     ADC_InitStructure.ADC_ScanConvMode = ENABLE;
     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
     ADC_InitStructure.ADC_NbrOfChannel = 3;
     ADC_RegularChannelConfig( VOLUMES_ADC, ADC_Channel_9,  1, ADC_SampleTime_1Cycles5 );
     ADC_RegularChannelConfig( VOLUMES_ADC, ADC_Channel_8,  2, ADC_SampleTime_1Cycles5 );
     ADC_RegularChannelConfig( VOLUMES_ADC, ADC_Channel_15, 3, ADC_SampleTime_1Cycles5 );
  ADC_DeInit( VOLUMES_ADC );           // Put everything back to power-on defaults 
     ADC_Init( VOLUMES_ADC, &ADC_InitStructure );
     ADC_DMACmd( VOLUMES_ADC, ENABLE );
     //ADC_ITConfig (VOLUMES_ADC, ADC_IT_EOC, ENABLE);
     
     // DMA Configuration --------------------------------------------
     VOLUMES_DMA_RCC_INIT();
  DMA_DeInit( DMA1_Channel1 );
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) (&(ADC1->DR));
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(volume_buff);
  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_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init( DMA1_Channel1, &DMA_InitStructure );
     DMA_ITConfig( DMA1_Channel1, DMA_IT_TC, ENABLE );
     
     NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel1_IRQn;
     NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
     NVIC_InitStruct.NVIC_IRQChannelSubPriority  = 1;
     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStruct);
     // TIMERS initialization ----------------------------------------
     // 36MHz / 4 = 9MHz / 25 = 360KHz / 45 = 8KHz
     TIMER_VOLUMES_RCC_INIT();     
     TIM_Cmd( TIMER_VOLUMES, DISABLE );     
     TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV4; 
     TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
     TIM_InitStruct.TIM_Period = 100; // it seems that this timer clock is 72MHz!!!
     TIM_InitStruct.TIM_Prescaler = 18000;
     TIM_InitStruct.TIM_RepetitionCounter = 0;
     TIM_TimeBaseInit( TIMER_VOLUMES, &TIM_InitStruct );
     TIM_ITConfig( TIMER_VOLUMES, TIM_IT_Update, ENABLE );
     
     NVIC_InitStruct.NVIC_IRQChannel = TIMER_VOLUMES_IRQn;
     NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
     NVIC_InitStruct.NVIC_IRQChannelSubPriority  = 0;
     NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStruct);
     // starting -----------------------------
     TIM_TimeBaseInit( TIMER_VOLUMES, &TIM_InitStruct );
     DMA_Cmd( VOLUMES_DMA_Channel, ENABLE );
     ADC_Cmd( VOLUMES_ADC, ENABLE );
     TIM_Cmd( TIMER_VOLUMES, ENABLE );     
}

and timer software start conversion IRQ handler is 

void TIMER_VOLUMES_IRQHandler(void)
{
     GPIO_ResetBits (SENSORS_GND_GPIO, SENSORS_GND_GPIO_PIN);
     ADC_SoftwareStartConvCmd (VOLUMES_ADC, ENABLE);
     TIM_ClearITPendingBit ( TIMER_VOLUMES, TIM_IT_Update);
}

and DMA IRQ handler is 

void DMA1_Channel1_IRQHandler(void)
{
     GPIO_SetBits (SENSORS_GND_GPIO, SENSORS_GND_GPIO_PIN);
     DMA_ClearITPendingBit (DMA1_IT_GL1);
}

the buffer is defined as

uint32_t          vol[3];

and the config function is called as

Volumes_init( vol );

the problem is that, after dma transfer complete interrupt, the data in memory address is not correct and it seems that only a wrong byte is transferred in every dma requst and a byte increment is done afterward
I mean only first element of vol (vol[0]) has value of 3 bytes and its bytes seems to be nonsense

I can't understand what is wrong here

can anyone help me?

Outcomes