AnsweredAssumed Answered

contiously reading ADC

Question asked by robitzki.torsten on Jun 22, 2015
Latest reply on Jun 23, 2015 by robitzki.torsten
Hello,
I have a tiny application on an STM8L051F3 (current developing hardware is a STM8L152C6), where I need to sample an analog voltage and to send that voltage every once in a while to an i2c bus. To make easy things easy, I just thought of starting the ADC, store the result in the ADCs ISR and restart the ADC from within the ISR. Then use a main loop, to access the sampled voltage and to send it on the i2c bus. Now my problem is, that I do get the ISR served, but I can’t read values that make sense (checked by sending them to a terminal via an UART). I read values that change (in the range ~0x7ed to 0x80d).

According to the documentation, it should be quit simple: Switch on the ADC, select single conversion mode, disable DMA, select the right channel and start conversion. As I’ve read values that have some jitter, I’ve double checked, that I’m using the right channel (pin PB0; Channel 18). What else puzzles me a little bit, is that when I read the ADC1->SR, not only the „End of Conversion“ (EOC) bit set, but also the „Overrun“-Bit (OVER). According to the documentation, the Overrun bit is just used in Continuous Conversion mode.

Here is my initializing of the ADC:

void ADC_Init(void)
{
    CLK->PCKENR2 |= 0x01; /* Enable clock to ADC */

    // Switch on ADC
    ADC1->CR1 = 1;
    delay( 2 );

    /* reset all interrupt flags */
    ADC1->SR &= ~0x07;

    /* disable DMA for single conversion */
    ADC1->SQR[1] |= 0x80;

    /* PB0 (channel 18) for STM8L051F3 and STM8L152C6 */
    ADC1->SQR[2] = 1 << (18 - 16);

    /* 12 bit resolution
       Interruptenable for end of conversion
       single conversion
       Conversion start
       ON */
    ADC1->CR1 = 0x09;

    /* conversion start */
    ADC1->CR1 |= 2;
}

and here is the ISR:

void ADCInterruptHandle (void) __interrupt( 18 )
{
    uint8_t low, high;

    low  = ADC1->DRL;
    high = ADC1->DRH;

    voltage = low | ( high << 8 );

    /* conversion start */
    ADC1->CR1 |= 2;
}

Currently in my main loop, I just send `voltage` every second via UART. What could be my problem here? Any example, that comes close to my use case?

Thank you very much in advance for any help, tipp or pointers,

Torsten

Outcomes