Skip to main content
Explorer
February 9, 2024
Solved

L412 ADC gets different results on consecutive reads

  • February 9, 2024
  • 9 replies
  • 2382 views

I am using STM32L412KBU and read in different ADC channels.

Now I see that the first read returns 23451, the second read immediately after returns 20338.

I use x16 OVS, hence the big numbers.

After the second read, values seem to become stable.

external circuit is as follows

 ba_0-1707466859583.png

ADC and pin config

 

 

 GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
 GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
 LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
 ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
 ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
 LL_ADC_Init(ADC1, &ADC_InitStruct);
 ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
 ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
 ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
 ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
 ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
 ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
 LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
 LL_ADC_ConfigOverSamplingRatioShift(ADC1, LL_ADC_OVS_RATIO_16, LL_ADC_OVS_SHIFT_NONE);
 LL_ADC_SetOverSamplingDiscont(ADC1, LL_ADC_OVS_REG_CONT);
 ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1;
 ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;
 LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
 LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1), LL_ADC_PATH_INTERNAL_NONE);

 /* Disable ADC deep power down (enabled by default after reset state) */
 LL_ADC_DisableDeepPowerDown(ADC1);
 /* Enable ADC internal voltage regulator */
 LL_ADC_EnableInternalRegulator(ADC1);

 

 

this is how I read the ADC

 

 LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_15);
 LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SAMPLINGTIME_2CYCLES_5);
 LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SINGLE_ENDED);
 	LL_ADC_REG_StartConversion(ADC1);
 	while(LL_ADC_REG_IsConversionOngoing(ADC1));
 	PB0_ADC_value = LL_ADC_REG_ReadConversionData32(ADC1);
 	LL_ADC_REG_StartConversion(ADC1);
 	while(LL_ADC_REG_IsConversionOngoing(ADC1));
 	PB0_ADC_value = LL_ADC_REG_ReadConversionData32(ADC1);
 	LL_ADC_REG_StartConversion(ADC1);
 	while(LL_ADC_REG_IsConversionOngoing(ADC1));
 	PB0_ADC_value = LL_ADC_REG_ReadConversionData32(ADC1);
 	LL_ADC_REG_StartConversion(ADC1);
 	while(LL_ADC_REG_IsConversionOngoing(ADC1));
 	PB0_ADC_value = LL_ADC_REG_ReadConversionData32(ADC1);

 

    This topic has been closed for replies.
    Best answer by Peter BENSCH

    Anyway, the time constant of the resulting RC network is well into the millisecond range due to the 100nF, which must of course be taken into account. A pull-up in the order of 40kohms will also have a significant influence, which is why you need to give the system enough time to settle.

    9 replies

    b.a.Author
    Explorer
    February 9, 2024

    the above was in debug-mode with breakpoints...
    if I let the code run normally, just a consecutive read is not enough, the values decrease only slightly from one read to the next.

    To get to stable values, I have to add a 10ms delay at least

    Technical Moderator
    February 9, 2024

    Well, since in your case it is a high-impedance temperature measurement with some significant capacitor, which is therefore very slow, you should set the ADC from 2.5 cycles to the slowest 640.5 cycles.

    Regards
    /Peter

    b.a.Author
    Explorer
    February 9, 2024

    well, my thoughts went that way too

    But I reasoned that it should only be relevant after powering up the system, not when it is running and I merely reset the controller...

    changing to 640,5 cycles did not change the behaviour relevantly 

    b.a.Author
    Explorer
    February 9, 2024

    I also notice a drastic change in returned ADC value depending on if and where I set a breakpoint before the read.

    Setting a breakpoint before the GPIO gets set to analog (line 1 in the below code) returns 39897

    line 5 : 19913

     

    Might this be because the pin was configured as input with pullup right before?

     

     GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
     GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
     GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
     LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
     LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_15);
     LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SAMPLINGTIME_640CYCLES_5);
     LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_15, LL_ADC_SINGLE_ENDED);
     	LL_ADC_REG_StartConversion(ADC1);
     	while(LL_ADC_REG_IsConversionOngoing(ADC1));
     	PB0_ADC_value = LL_ADC_REG_ReadConversionData32(ADC1);
     	LL_ADC_REG_StartConversion(ADC1);
     	while(LL_ADC_REG_IsConversionOngoing(ADC1));
     	PB0_ADC_value1 = LL_ADC_REG_ReadConversionData32(ADC1);
     	LL_ADC_REG_StartConversion(ADC1);
     	while(LL_ADC_REG_IsConversionOngoing(ADC1));
     	PB0_ADC_value2 = LL_ADC_REG_ReadConversionData32(ADC1);
     	LL_mDelay(20);
     	LL_ADC_REG_StartConversion(ADC1);
     	while(LL_ADC_REG_IsConversionOngoing(ADC1));
     	PB0_ADC_value3 = LL_ADC_REG_ReadConversionData32(ADC1);

     (line 1 

    Graduate II
    February 9, 2024

    If you have a multi-voltage setup, check that there is no positive injection on some pin.

    b.a.Author
    Explorer
    February 9, 2024

    everything is powered by the same 3,3V supply

    Technical Moderator
    February 9, 2024

    Anyway, the time constant of the resulting RC network is well into the millisecond range due to the 100nF, which must of course be taken into account. A pull-up in the order of 40kohms will also have a significant influence, which is why you need to give the system enough time to settle.

    b.a.Author
    Explorer
    February 9, 2024

    so this behaviour can be explained by the big capacitor and the fact the just before, the pin had the internal pull-up connected?

    Technical Moderator
    February 9, 2024

    Just give it a try.

    b.a.Author
    Explorer
    February 9, 2024

    I now left all the relevant pins in RESET_STATE and ADC readings are "immediately" correct!

    Initializing them as GPIO_ANALOG has of course the same effect

    Thanks for pointing me in the right direction!