cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f4 triggered ADC, Data corruption

usama
Associate II
Posted on March 27, 2014 at 15:55

Hi,

I have been playing with ADC of stm32f4, i triggered ADC with TIM4_CC4 event to sample at 8Khz, using DMA. All individual components are working well but once combined i get alternate samples missing, i observe it using debugger. Data is correct as i am giving sinusoidal signal and data values seems to be correct but every alternate sample is simply 0. I am posting my code if anyone could guide, it would be great help.

ADC_InitTypeDef       ADC_InitStructure;

  ADC_CommonInitTypeDef ADC_CommonInitStructure;

  DMA_InitTypeDef       DMA_InitStructure;

  /* RCC clock settings and GPIO settings for ADC3 channel 11 */

  RCC_Configuration_ADC3();

  GPIO_Configuration_ADC3();

  TIM4_Configuration(); // set at 8KHz

  /* NVIC interrupt enable for DMA2 Stream0 */

  ADC3_DMA2_Stream0_Interrupt_Enable();

  /* RCC clock settings for DMA2 */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

  /* DMA2 Stream0 channel2 configuration **************************************/

  DMA_InitStructure.DMA_Channel = DMA_Channel_2;

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCRxBuffer1;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;

  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_HalfWord;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  /* Enable Double Buffer Mode */

  DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)&ADCRxBuffer2,DMA_Memory_0);

  /* Clear Transfer Complete flag bit for DMA2_Stream0 transfer Complete */

  DMA_ClearITPendingBit(DMA2_Stream0,DMA_FLAG_TCIF0);

  DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);

  DMA_ITConfig(DMA2_Stream0,DMA_IT_TC,ENABLE);

  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* ADC Common Init **********************************************************/

  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Init ****************************************************************/

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 1;

  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channel11 configuration *************************************/

  ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_3Cycles);

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

  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */

  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC3 */

  ADC_Cmd(ADC3, ENABLE);

#stm32f4 #stm32 #discovery #selective-cut-n-paste #adc-and-dma
10 REPLIES 10
Posted on March 28, 2014 at 01:35

It's incomplete so really hard to do much analysis. I don't think you've got the secondary memory buffer defined properly. Your description of the corruption isn't particularly clear, the way it's explained Sample[0], Sample[2] are good, Sample[1], Sample[3] are bad? Or does it mean the Ping buffer is good, and the Pong buffer is bad? Lacking any example data it's hard to tell.

The debugger does not stop DMA, it might stop a suitably configured timer.

At 8 KHz a sample time of 3 would seem to be very short, and likely given pretty awful readings.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
usama
Associate II
Posted on March 28, 2014 at 07:43

Hi clive,

sample_buffer_ping[0] &[2] is correct, sample_buffer_ping[1] & [3] = 0 and so on...

sample_buffer_pong[0] &[2] is correct, sample_buffer_pong[1] & [3] = 0 and so on...

same behavior is observed for both the buffers... 

i used the same DMA double buffer configuration for duplex I2S interface and it was working good. 

have increased sample time still no success.

As i am giving sinusoidal signal and correct data [0] & [2] seems to be making sinusoidal signal.

Each buffer size is 1024, and it is taking 128ms for each buffer to fill completely which is correct for 8kHz sampling time. 

example data :

buffer1 = {2722, 0, 2162, 0, 1535, 0, 1226, 0, 1453, 0, 2049, 0, 2647, 0, 2869, 0, 2576, 0, 1962, 0, 1400, 0, 1240, 0, 1610,.....}

buffer 2 = {1242, 0, 1380, 0, 1933, 0, 2571, 0, 2865, 0, 2656, 0, 2049, 0, 1458, 0, 1231, 0, 1526, 0, 2125, 0, 2707, 0, 2868,.....}

usama
Associate II
Posted on March 28, 2014 at 07:44

/*

HCLK = 168MHz

TIM4_CLK = 84MHz

*/

Tim4_configuration()

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

/* TIM4 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

/* TIM4 configuration ------------------------------------------------------*/

/* Time Base configuration */

TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Period = 10500;

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_ClockDivision = 1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

/* TIM4 channel4 configuration in PWM mode */

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = 0x7F;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

TIM_OC4Init(TIM4, &TIM_OCInitStructure);

TIM_Cmd(TIM4,ENABLE);

}

Posted on March 28, 2014 at 08:38

Again completeness seems to allude us, please refer to the examples I post to understand what I'm asking for. It means the solution must be free standing, and compilable.

Based on the description, I'm going to guess you're not reading the right values via DMA, and whatever you've define ADC3_DR_ADDRESS is incorrect.

Change :

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

to

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
usama
Associate II
Posted on March 28, 2014 at 10:17

#define BUFFER_SIZE 1024

/* Double Buffer Memory */

__IO uint16_t ADCRxBuffer1[BUFFER_SIZE];  /* Memory 0 */

__IO uint16_t ADCRxBuffer2[BUFFER_SIZE];  /* Memory 1 */

void DMA2_Stream0_IRQHandler()

{

if(DMA_GetFlagStatus(DMA2_Stream0,DMA_FLAG_TCIF0) == SET)

{

if(DMA_GetCurrentMemoryTarget(DMA2_Stream0) == 0)

{

/* Turn on-board LEDs ON */

}

else if(DMA_GetCurrentMemoryTarget(DMA2_Stream0) == 1)

{

/* Turn on-board LEDs OFF */

}

}

DMA_ClearITPendingBit(DMA2_Stream0,DMA_FLAG_TCIF0);

}

int main(void)

{

SystemInit();

ADC3_CH11_DMA_Configuration();

    while(1)

    {

    }

}

void ADC3_CH11_DMA_Configuration(void)

{

  ADC_InitTypeDef       ADC_InitStructure;

  ADC_CommonInitTypeDef ADC_CommonInitStructure;

  DMA_InitTypeDef       DMA_InitStructure;

  /* RCC clock settings and GPIO settings for ADC3 channel 11 */

  RCC_Configuration_ADC3();

  GPIO_Configuration_ADC3();

  TIM4_Configuration();

  /* NVIC interrupt enable for DMA2 Stream0 */

  ADC3_DMA2_Stream0_Interrupt_Enable();

  /* RCC clock settings for DMA2 */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

  /* DMA2 Stream0 channel2 configuration **************************************/

  DMA_InitStructure.DMA_Channel = DMA_Channel_2;

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

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCRxBuffer1;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;

  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_HalfWord;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  /* Enable Double Buffer Mode */

  DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)&ADCRxBuffer2,DMA_Memory_0);

  /* Clear Transfer Complete flag bit for DMA2_Stream0 transfer Complete */

  DMA_ClearITPendingBit(DMA2_Stream0,DMA_FLAG_TCIF0);

  DMA_DoubleBufferModeCmd(DMA2_Stream0,ENABLE);

  DMA_ITConfig(DMA2_Stream0,DMA_IT_TC,ENABLE);

  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* ADC Common Init **********************************************************/

  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Init ****************************************************************/

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Falling;

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 1;

  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channel11 configuration *************************************/

  ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_15Cycles);

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

  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */

  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC3 */

  ADC_Cmd(ADC3, ENABLE);

}

void ADC3_DMA2_Stream0_Interrupt_Enable(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

/* Enable the DMA2_Stream0 Interrupt */

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);

}

void TIM4_Configuration(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

/* TIM4 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

/* TIM4 configuration ------------------------------------------------------*/

/* Time Base configuration */

TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Period = 10500;

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_ClockDivision = 1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

/* TIM4 channel4 configuration in PWM mode */

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = 0xf;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC4Init(TIM4, &TIM_OCInitStructure);

TIM_Cmd(TIM4,ENABLE);

}

void RCC_Configuration_ADC3(void)

{

  //for ADC3 on PC1 using IN11

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

}

void GPIO_Configuration_ADC3(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_StructInit(&GPIO_InitStructure);

  //for ADC3 on PC1 using IN10

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

}

usama
Associate II
Posted on March 28, 2014 at 10:21

Hi clive,

Thanks for your response, i have posted compilable version of complete code. kindly have a look.

Change :

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

to

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

 

also not solved the problem,

ADC3_DR_ADDRESS = 0x4001224C which is the actual address of ADC3 data register. 

Posted on March 28, 2014 at 17:14

Seems to work fine for me, what are you debugging with? CooCox?

0690X00000605Y3QAI.png
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
usama
Associate II
Posted on March 29, 2014 at 12:31

Thanks alot clive for your support, my problem is solved now. I was indeed debugging with coocox. Problem was a ridiculous mistake on my end. Now i am able to make ADC & DAC to work at 8kHz with double buffer DMA at both ends. Thanks again. 

puneethj
Associate II
Posted on July 13, 2015 at 11:58

Hi Mr. Clive,  I have just started to work on STM32F4 board and I am using COOCOX software, Is this a bad choice? I should work on ADC DMA and CAN peripherals, Where can i get best examples for DMA and CAN? Is it COOCOX or something else, Thank You Sir