AnsweredAssumed Answered

Unexpected readings (2X or 0.5X) using ADC on STM32F0

Question asked by Osman Eralp on Nov 10, 2014
Latest reply on Nov 10, 2014 by Clive One
I'm using the ADC on a STM32F072RBT6 to read a constant voltage that is derived from my supply voltage. Sometimes, I get a reading that is twice the expected value, and sometimes I get a reading that is half the expected value. The following data shows this problem:

...
t 70210  v 46  ref 1228
t 70220  v 47  ref 1228
t 70230  v 89  ref 1229  <-- unexpected reading (2x)
t 70240  v 45  ref 1228
t 70250  v 47  ref 1228
t 70260  v 49  ref 1228
t 70270  v 45  ref 1229
t 70280  v 49  ref 1229
t 70290  v 41  ref 1228
t 70300  v 48  ref 1228
t 70310  v 24  ref 1229  <-- unexpected reading (0.5x)
t 70310  v 47  ref 1228
t 70320  v 48  ref 1229
t 70330  v 48  ref 1228
t 70340  v 47  ref 1228
...

The expected value of v is about 48.

Does any know of anything related to the STM32F0 that might cause this problem? It seems like the SAR sometimes is off by one comparison. But the ref voltage doesn't show the problem.

My ADC init code is shown below.

TIA,
Osman


/******************************************************************************/
void RCC_Configuration(void)
{
  /* GPIOC clock enable */
  //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
 
  /* ADC1 Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
 
  /* DMA1 clock enable */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
   
  //RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
  //RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
}
 
  
/******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
 
  /* ADC Channel 10 -> PC0 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
}
  
  
/******************************************************************************/
void DMA_Configuration(void)
{
  
  DMA_InitTypeDef DMA_InitStructure;
 
  /* DMA1 Channel1 Config */
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCData;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 2;
  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); 
   
  
}
 
 
/******************************************************************************/
void ADC_Configuration(void)
{
  ADC_InitTypeDef ADC_InitStructure;
  uint32_t calibrationFactor;
  
  /* Initialize ADC structure */
  ADC_StructInit(&ADC_InitStructure);
   
  /* ADC1 Init */
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
  ADC_Init(ADC1, &ADC_InitStructure);
  
  /* ADC1 regular channel 10 configuration */
  ADC_ChannelConfig(ADC1, ADC_Channel_10, ADC_SampleTime_55_5Cycles); // PC0
  
  /* Convert the ADC1 Vref  with 55.5 Cycles as sampling time */
  ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);
  ADC_VrefintCmd(ENABLE);
   
  /* ADC1 Calibration */
  calibrationFactor = ADC_GetCalibrationFactor(ADC1);
  
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  
  /* Wait the ADCEN falg */
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
  
  /* ADC1 regular Software Start Conv */
  ADC_StartOfConversion(ADC1);
}
  
 
/******************************************************************************/
  
void initADC(void)
{
  int i;
  char obuf[OBUF_SIZE];
  uint16_t mSense, ref;
 
  /* ADC1 DeInit */ 
  ADC_DeInit(ADC1);
   
  RCC_Configuration();
  GPIO_Configuration();
  DMA_Configuration();
  ADC_Configuration();
  
  i = 0;
  
  while(1) {
    waitForTick();
 
    mSense = (uint32_t)((ADCData[0]* 3300) / 0xFFF);
    ref =    (uint32_t)((ADCData[1]* 3300) / 0xFFF); 
  
    if (i++ == 0) {
      snprintf(obuf,OBUF_SIZE,"t %ld  v %ld  ref %ld\n\r", timer_g, mSense, ref);
      writeUSART(USART1,obuf);
    }
    i %= 10;
  }
}


Outcomes