AnsweredAssumed Answered

ADC STM32F0 DISCO shows big noise

Question asked by scholle.steffen on Jun 11, 2014
Edit: Ok, I used the scope and measured the signals. Actually there is a lot of noise on the inputs. Also connecting the pins directly to ground isn't a good idea as well.
So, I guess this threat can be closed.

I'm using the STM32F0308-DISCO and sample data with the ADC at Ports PA4...PA7.
It seems like the values are very inacurate and alternating a lot.
I connected the pins to ground and got values between 0...2D or similar.
If I attach some external voltage the values are getting even worse (for example 2V). I get valuese betweet 0...255 for the low byte. I think there is something wrong with the DMA, because this can't be a hardware issue.

// STM32 ADC 4 Channel DMA/TIM USART2 STM32F0-Discovery sourcer32@gmail.com
  
#include "stm32f0xx.h"
  
//**************************************************************************************
  
#define SAMPLES 4
  
volatile uint16_t RegularConvData[SAMPLES];
uint16_t  ADC1ConvertedValue1 = 0, ADC1ConvertedValue1_low = 0, ADC1ConvertedValue1_high = 0;
  
void ADC_TIM_DMA_Configuration(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  TIM_OCInitTypeDef TIM_OCInitStructure;
  ADC_InitTypeDef ADC_InitStructure;
  DMA_InitTypeDef DMA_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);
  
  /* 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 = 1000 - 1; // 1 KHz
  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_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 = SAMPLES;
  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);
  
  /* Initialize ADC structure */
  ADC_StructInit(&ADC_InitStructure);
  
  /* Configure the ADC1 in continous mode withe a resolutuion equal to 12 bits  */
  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);
  
  /* Convert the  ADC_Channnel_0  with 7.5 Cycles as sampling time */
  ADC_ChannelConfig(ADC1, ADC_Channel_4 , ADC_SampleTime_1_5Cycles);
  
  /* Convert the  ADC_Channnel_1  with 7.5 Cycles as sampling time */
  ADC_ChannelConfig(ADC1, ADC_Channel_5 , ADC_SampleTime_1_5Cycles);
  
  /* Convert the  ADC_Channnel_2  with 7.5 Cycles as sampling time */
  ADC_ChannelConfig(ADC1, ADC_Channel_6 , ADC_SampleTime_1_5Cycles);
  
  /* Convert the  ADC_Channnel_3  with 7.5 Cycles as sampling time */
  ADC_ChannelConfig(ADC1, ADC_Channel_7 , ADC_SampleTime_1_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);
}
  
//**************************************************************************************
  
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* GPIOA Periph clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
  
  /* Configure ADC Channels as analog input - might conflict */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  /* Configure USART pins */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1); // USART2_TX
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1); // USART2_RX
}
  
//**************************************************************************************
  
void USART_Configuration(void)
{
  USART_InitTypeDef USART_InitStructure;
  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
  
  /* USART2 9600 8N1 */
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART2, &USART_InitStructure);
  
  USART_Cmd(USART2, ENABLE);
}
  
//**************************************************************************************
  
char USART_GetChar(void)
{
  while(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET); // Wait For input character
  
  return((char)USART_ReceiveData(USART2));
}
  
//**************************************************************************************
  
void USART_PutChar(char ch)
{
  while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); // Wait for holding buffer empty
  
  USART_SendData(USART2, ch);
}
  
//**************************************************************************************
  
void USART_PutString(char *s)
{
  while(*s)
    USART_PutChar(*s++);
}
  
//**************************************************************************************
  
void USART_PutDecimal(unsigned int i)
{
  char String[16];
  char *s = String + sizeof(String);
  
  *--s = 0; // NUL
  
  do
  {
    *--s = '0' + (char)(i % 10);
    i /= 10;
  }
  while(i);
  
  USART_PutString(s);
}
  
//**************************************************************************************
  
int main(void)
{
  GPIO_Configuration();
  
  ADC_TIM_DMA_Configuration();
  
  USART_Configuration();
  
  while(1)
  {
    char ch;
  
    ch = USART_GetChar();
  
    if (ch == '#')
    {
            ADC1ConvertedValue1 = RegularConvData[0];
            ADC1ConvertedValue1_low = ADC1ConvertedValue1&0xFF;
            ADC1ConvertedValue1_high = ADC1ConvertedValue1>>8;
             
      USART_PutChar(ADC1ConvertedValue1_low); // PA7
            USART_PutChar(ADC1ConvertedValue1_high);
             
            ADC1ConvertedValue1 = RegularConvData[1]&0xFF;
      USART_PutChar(ADC1ConvertedValue1); // PA4
            ADC1ConvertedValue1 = RegularConvData[1]>>8;
            USART_PutChar(ADC1ConvertedValue1);    }
         
            ADC1ConvertedValue1 = RegularConvData[2]&0xFF;
      USART_PutChar(ADC1ConvertedValue1); // PA5
            ADC1ConvertedValue1 = RegularConvData[2]>>8;
            USART_PutChar(ADC1ConvertedValue1);
             
          ADC1ConvertedValue1 = RegularConvData[3]&0xFF;
      USART_PutChar(ADC1ConvertedValue1); // PA6
            ADC1ConvertedValue1 = RegularConvData[3]>>8;
            USART_PutChar(ADC1ConvertedValue1);
  }
}
  
//**************************************************************************************
  
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  
  /* Infinite loop */
  while (1)
  {}
}
#endif

Outcomes