Skip to main content
Denis Gottardello
Associate III
January 19, 2018
Question

STM32, ADC and continuous conversion mode

  • January 19, 2018
  • 5 replies
  • 2432 views
Posted on January 19, 2018 at 23:16

Hi. I need to have the value of 2 channels and the internal temperature.

My adc is setup as this:

  hadc.Instance = ADC1;

  hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

  hadc.Init.Resolution = ADC_RESOLUTION_12B;

  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

  hadc.Init.LowPowerAutoWait = DISABLE;

  hadc.Init.LowPowerAutoPowerOff = DISABLE;

  hadc.Init.ContinuousConvMode = DISABLE;

  hadc.Init.DiscontinuousConvMode = DISABLE;

  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

  hadc.Init.DMAContinuousRequests = DISABLE;

  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;

and this is my callback:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {

    if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)) {

        ADCValues[ADCIndex]= HAL_ADC_GetValue(hadc);

        ADCIndex++;

    }

    if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS)) {

        ADCIndex= 0;

        Vdd= 3300 * (*VREFINT_CAL_ADDR) / ADCValues[3];

        Temperature= (((int32_t)ADCValues[2] * Vdd / 3300)- (int32_t)*TEMP30_CAL_ADDR);

        Temperature= Temperature * (int32_t)(110- 30);

        Temperature= Temperature / (int32_t)(*TEMP110_CAL_ADDR- *TEMP30_CAL_ADDR);

        Temperature= Temperature+ 30;

        Reader125_0= ADCValues[1];

        Reader125_1= ADCValues[0];

    }

}

everything is working perfectly but only with 'hadc.Init.ContinuousConvMode = DISABLE;'

If I enable 'hadc.Init.ContinuousConvMode' I have wrong values.

What can I do to resolve the problem?

    This topic has been closed for replies.

    5 replies

    raptorhal2
    Lead
    January 20, 2018
    Posted on January 20, 2018 at 01:48

    If the EOS processing takes longer than one ADC conversion, the next EOC process will be for the second or later conversion, out of sync with the ADCIndex.

    If for some reason you can't disable continuous mode, try converting VREF or Temperature first where, I presume, you have the longer sampling times needed for accuracy. But you then run the risk that might not work for a different combination of ADC clock and system clock.

    Cheers, Hal

    T J
    Senior III
    January 20, 2018
    Posted on January 20, 2018 at 07:28

    yes, the values go crazy down here;

    ADC_CLOCK_ASYNC_DIV1

    and   ADC_SAMPLETIME_1CYCLE_5

    what sample time are you using ?

    you really have to calibrate the ADC too, if you want some accuracy in the readings

    Denis Gottardello
    Associate III
    January 20, 2018
    Posted on January 20, 2018 at 09:35

    Finally this is my CubeMX setup

    0690X00000609RPQAY.png0690X00000609RUQAY.png

    This is my callback

    unsigned int ADCValues[5];

    unsigned int ADCIndex= 0;

    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {

        if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)) {

            ADCValues[ADCIndex]= HAL_ADC_GetValue(hadc);

            ADCIndex++;

        }

        if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS)) ADCIndex= 0;

    }

    And outside che callback I check the ADCValues[2] and ADCValues[3] where I should have the Temperature and Vdd values.

    Is this the right approach? The Temperature value now seems to be ok.
    T J
    Senior III
    January 20, 2018
    Posted on January 20, 2018 at 12:06

    I have a similar approach,

    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
     if(!ADC_ChannelsCounter--) {
     ADC_ChannelsCounter = ADC_ChannelCount;
     ADC_CompleteCycle = true; // signal foreground to process 
     // copy 15 channels results away now
     for(int i = 0 ; i < ADC_ChannelCount ; i++) { 
     ADC_Channel_Buffer[i] = ADC_DMABuffer[i]; 
     }
     }
    }�?�?�?�?�?�?�?�?�?�?�?�?