AnsweredAssumed Answered

STM32L1: ADC "generates" signal?

Question asked by moktor on Jul 3, 2014
Latest reply on Jul 4, 2014 by moktor
After I discovered finally managed to get the ADC and DMA to run and play well together I ran into a very strange problem:

While checking the results of my AD conversions in the debugger, I realised that the values must be off. Even when measuring the VREFINT channel, I got a value that was too high and the VDDA I calculated from this value was therefore about 0.5V(!) too low!

So I pulled out an oscilloscope to check what happens. After a long time trying to isolate the problem, I realised that the ADC "generates a triangular signal". This "signal" corresponds to the conversion time. At the lowest conversion time, the signal has an offset of around 600mV(!) and an amplitude of around 20mV, while at higher conversion times, the offset is lower (down to about 60mV) and the amplitude higher (up to around 60mV).

The period of the signal corresponds exactly to the configured cycle time + delay time. This seems to happen independently of the channel measured. The phenomenon is observable about as soon as the AD starts conversion (SWSTART bit set) and stops as soon as the conversion ends (SQRx reg written to).

Although in my example I do continuous conversions, it appears to happen with single conversions and scan conversions as well.

Did anyone ever encounter this phenomenon?
Does anyone have an idea where this problem may come from?

In the following (IAR!) code, which I used to test this phenomenon, I marked the lines with SWSTART and SQRx written to:

001.int main()
002.{
003.  RCC_AHBENR_bit.GPIOAEN = 1;
004.  RCC_AHBENR_bit.GPIOBEN = 1;
005.  
006.  GPIOB_PUPDR_bit.PUPDR1 = 0;
007.  GPIOB_MODER_bit.MODER0 = 3;
008.  GPIOB_OTYPER_bit.OT0 = 0;
009.     
010.    if (RCC_CR_bit.HSION == 0)
011.  {
012.    while (PWR_CSR_bit.VOSF)
013.    {
014.      /* wait for stable voltage range */
015.    }
016. 
017.    // set voltage range.
018.    PWR_CR_bit.VOS = 1;
019.    while (PWR_CSR_bit.VOSF)
020.    {
021.      /* wait for stable voltage range */
022.    }
023. 
024.    // HSI 16MHz oscillator on
025.    RCC_CR_bit.HSION = 1;
026.    while (!RCC_CR_bit.HSIRDY)
027.    {
028.      // wait until HSI is stable
029.    }
030.  }
031.  
032.  if (!RCC_CFGR_bit.SW)
033.    {
034.      RCC_CFGR_bit.SW = 1;
035.    }
036.     
037.  while (1)
038.  {
039.  /* enable peripheral clock */
040.  RCC_APB2ENR_bit.ADC1EN = 1;
041. 
042.  /* prescaler for ADCCLK */
043.  ADC_CCR_bit.ADCPRE = 0;
044.  
045.  /* set ADC Resolution */
046.  ADC_CR1_bit.RES = 0;
047.  
048.  /* right alignment of result */
049.  ADC_CR2_bit.ALIGN = 0;
050. 
051.  /* set conversion time via cycles register */
052.  ADC_SMPR3_bit.SMP9 = 0;
053.  
054.  /* delay after conversion => no delay */
055.  ADC_CR2_bit.DELS = 0;
056. 
057.  /* overrun interrupt enable */
058.  ADC_CR1_bit.OVRIE = 1;
059.  SETENA0_bit.ADC1 = 1;
060.  
061.  /* which channel to sample */
062.  ADC_SQR5_bit.SQ1 = 9;
063.  ADC_SQR1_bit.L = 0;
064.  
065.  if (!ADC_SR_bit.ADONS)
066.  {
067.    /* ADC not running; power up the adc module */
068.    ADC_CR2_bit.ADON = 1;
069.  
070.    while (!ADC_SR_bit.ADONS)
071.    {
072.      /* wait until the adc is ready */
073.    }
074.  }
075.  
076.  while (ADC_SR_bit.RCNR);
077.  {
078.    /* Wait for regular channel ready */
079.  }
080.     
081.    ADC_CR2_bit.CONT = 1;
082.    ADC_CR2_bit.SWSTART = 1;
083.     
084.    for (uint32_t i=0; i < 1024*1024; i++);
085.     
086.    ADC_SQR5 = 0;
087.     
088.    ADC_CR2_bit.ADON = 0;
089.     
090.    while (ADC_SR_bit.ADONS)
091.    {
092.      /* wait until the adc is ready */
093.    } // reset ADC registers. Required? Not really documented.
094.    RCC_APB2RSTR_bit.ADC1RST = 1;
095.    /* Release reset */
096.    RCC_APB2RSTR_bit.ADC1RST = 0;
097. 
098.    // disable peripherial clock
099.    RCC_APB2ENR_bit.ADC1EN = 0;
100.     
101.  }
102.  return 0;     // never reached
103.}

Please excuse the formatting; I did kind of copy/paste it from my actual driver code...

Outcomes