cancel
Showing results for 
Search instead for 
Did you mean: 

Noise with DMA/ADC

jmclaughlin2
Associate II
Posted on September 30, 2016 at 06:33

We are running a number of channels of ADC on the STM32F0-Discovery board. We have the code below configured to continually read the input signal levels.  The code is based on routines posted elsewhere in this forum.

The noise we are seeing is spikes which is very periodic. The code below gives about a 25KHz rate of noise. The noise appears on all the ADC pins. The noise doesn't start appearing until the StartConversion call.

If we don't use DMA and just use on-demand ADC almost all the noise is gone.

Here is an image of what the noise looks like:

0690X00000602QoQAI.bmp

We get the noise regardless of whether we are driving the inputs from an op-amp or other amounts of impedance.

Is there anything in the code that we can do to reduce this noise? Would changing SampleTime help?

What we ultimately want to do is to have the set of ADC inputs sampled around 5Hz and we need as much of the 12 bits resolution as possible.

volatile uint16_t RegularConvData[SAMPLES];

void ADC_Config(void)

{

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  TIM_OCInitTypeDef TIM_OCInitStructure;

  ADC_InitTypeDef ADC_InitStructure;

  DMA_InitTypeDef DMA_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

 

  // ADC1 DeInit 

  ADC_DeInit(ADC1);

 

  // ADC1 Periph clock enable

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM1, ENABLE);

 

  // DMA1 clock enable

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    // GPIO clock enable

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

 

  // Configure ADC Channels as analog input

  GPIO_StructInit(&GPIO_InitStructure);

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

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

  // TIM2 Configuration

  TIM_DeInit(TIM1);

 

  // Time base configuration

  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; // 1 MHz, from 48 MHz

  TIM_TimeBaseStructure.TIM_Period = 10 - 1; 

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

 

  // Output Compare PWM Mode configuration 

  TIM_OCStructInit(&TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // low edge by default 

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM_OCInitStructure.TIM_Pulse = 1;

  TIM_OC4Init(TIM1, &TIM_OCInitStructure);

 

  // TIM1 enable counter

  TIM_Cmd(TIM1, ENABLE);

 

  // Main Output Enable

  TIM_CtrlPWMOutputs(TIM1, ENABLE);

 

  // DMA1 Channel1 Config

  DMA_DeInit(DMA1_Channel1);

  DMA_StructInit(&DMA_InitStructure);

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

  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&RegularConvData[0];

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

  DMA_InitStructure.DMA_BufferSize = 6;

  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_M2M = DMA_M2M_Disable;

  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

 

  // DMA1 Channel1 enable 

  DMA_Cmd(DMA1_Channel1, ENABLE);

 

  // ADC DMA request in circular mode 

  ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);

 

  // Enable ADC_DMA 

  ADC_DMACmd(ADC1, ENABLE);

 

  // Configure the ADC1 in continous mode withe a resolution equal to 12 bits 

  ADC_StructInit(&ADC_InitStructure);

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

  ADC_InitStructure.ADC_ExternalTrigConv =  ADC_ExternalTrigConv_T1_CC4;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;

  ADC_Init(ADC1, &ADC_InitStructure);

    // initialize each ADC channel in order

  ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_7_5Cycles);

  ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_7_5Cycles);

  ADC_ChannelConfig(ADC1, ADC_Channel_2 , ADC_SampleTime_7_5Cycles);

  ADC_ChannelConfig(ADC1, ADC_Channel_3 , ADC_SampleTime_7_5Cycles);

  ADC_ChannelConfig(ADC1, ADC_Channel_4 , ADC_SampleTime_7_5Cycles);

  ADC_ChannelConfig(ADC1, ADC_Channel_5 , ADC_SampleTime_7_5Cycles);

  // ADC Calibration

  ADC_GetCalibrationFactor(ADC1);

 

  // Enable ADC1 

  ADC_Cmd(ADC1, ENABLE);

 

  // Wait the ADCEN flag 

  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));

 

  // ADC1 regular Software Start Conv 

  ADC_StartOfConversion(ADC1);

}

 

3 REPLIES 3
raptorhal2
Lead
Posted on October 02, 2016 at 21:36

Does the same noise show up in the conversion data ?

If the noise source end up being not fixable, the problem should be easily overcome with oversampling and averaging, since the 5Hz sampling is significantly smaller than the 25KHz noise.

Cheers, Hal

jmclaughlin2
Associate II
Posted on October 07, 2016 at 02:36

Hi Hal,

Yes the noise shows up in the conversion data.  The amplitude of the noise spikes varies so the amount of effect varies.  We have tried doing a set of 16 samples from each input and using the average. That helps reduce the noise effect, but it is still big enough that our data isn't valid.

If we turn off DMA and just do ''on-demand'' ADC, the noise is much less. We get one spike shortly after doing the ADC_StartOfConversion call.

Walid FTITI_O
Senior II
Posted on October 10, 2016 at 17:48

Hi dfwbrawler, 

The noise may come from spurious charge shots out of AD inputs. Try to eliminate that with the using of ''Averaging'' or ''Digital-signal filtering'' methods described in the application note

http://www.st.com/content/ccc/resource/technical/document/application_note/group0/3f/4c/a4/82/bd/63/4e/92/CD00211314/files/CD00211314.pdf/jcr:content/translations/en.CD00211314.pdf

''How to get the best ADC accuracy in STM32Fx Series and STM32L1 Series devices'' (page 22 and page 32)

-Hannibal-