cancel
Showing results for 
Search instead for 
Did you mean: 

ADC giving value of 4095 on all configured channel

shafin388
Associate

Hello Community,

I am working on a custom board using the STM32 MCU (STM32WLE5JCI6). I am configuring the ADC with two channels:

  • PB1 → ADC_IN5
  • PB3 → ADC_IN2

I performed the following test cases and observed unexpected ADC behavior.

Test Case 1

  • Applied VDD+ to Channel 2 (ADC_IN2)
  • Channel 5 (ADC_IN5) connected to GND

Observation:
Both ADC channels are reading 4095, even though Channel 5 is tied to GND.

Test Case 2

  • Applied VDD+ to Channel 5 (ADC_IN5)

Observation:
Instead of getting 4095 on Channel 5, both channels are reading approximately 1500.

I am also facing the same issue with another MCU: STM32L071KBT6TR.

Development tools being used:

  • STM32CubeIDE Version 2.1.0
  • STM32CubeMX Version 6.8.0

I have attached the main source file containing the ADC configuration for reference.

Could anyone please help identify what might be causing this issue?

Awaiting your valuable suggestions.

Thanks.

1 ACCEPTED SOLUTION

Accepted Solutions

Hi Andrew,

Resolved issue of ADC read after doing changes into ADC init configuration.

Thanks.

View solution in original post

6 REPLIES 6
Andrew Neil
Super User

Welcome to the forum.

 


@shafin388 wrote:

I am working on a custom board


In that case, you need to post the schematic - see:

How to write your question to maximize your chances to find a solution

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
Gyessine
ST Employee

Hello @shafin388 

I reviewed your main.c and noticed that the ADC channel initialization in MX_ADC_INIT() was commented out, and the channels are instead configured inside custom functions.

This is not the cleanest or most recommended approach, and it can lead to unexpected behavior, especially when using scan mode with multiple channels.

I recommend restoring the channel configuration in MX_ADC_INIT and using your custom functions only to start the ADC, read the conversion values, and stop the ADC.

Since you are working on a custom board, it is important to first validate a known-good software implementation. This will help you determine whether the issue comes from the software configuration or from the hardware itself.
BR
Gyessine

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

shafin388
Associate

Hello Gyessine,

Thanks for sharing your feedback.

I switched to test ADC issue on targeted STM32L071KBT6TR MCU. I did changes into MX_ADC_INIT() function as per your suggestion. After many attempts and helps from others, it was found that if I read only single channel after ADC start it is not giving an expected values but if I read from both channel with poll conversion, getting correct value for both channel as per input.

But I didn't understand why reading of both channel is required for this MCU category.

Please refer my code as shown here. Calibration is done only once before u32ADC_Read_Channels() function call.

static void MX_ADC_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

    hadc.Instance = ADC1;
    hadc.Init.OversamplingMode = DISABLE;
    hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc.Init.Resolution = ADC_RESOLUTION_12B;
    hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
    hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc.Init.ContinuousConvMode = DISABLE;
    hadc.Init.DiscontinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.DMAContinuousRequests = DISABLE;
    hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    hadc.Init.LowPowerAutoWait = DISABLE;
    hadc.Init.LowPowerFrequencyMode = ENABLE;
    hadc.Init.LowPowerAutoPowerOff = DISABLE;
    if (HAL_ADC_Init(&hadc) != HAL_OK)
    {
      Error_Handler();
    }

    /*
     * Set a default active channel so the ADC is ready for the first conversion.
     * current_meas.c will call HAL_ADC_ConfigChannel() before each measurement
     * to switch between CH0 (PA0/PH2) and CH1 (PA1/PH1).
     * Note: sConfig has no SamplingTime member on STM32L0 — it is global (above).
     */

    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
      Error_Handler();
    }

    sConfig.Channel = ADC_CHANNEL_1;
    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
      Error_Handler();
    }
}
static uint32_t u32ADC_Read_Channels(uint32_t channel)
{
    uint32_t u32CH0_ADC;
    uint32_t u32CH1_ADC;

    if (HAL_ADC_Start(&hadc) != HAL_OK)
    {
      /* Start Error */
      Error_Handler();
    }

    /** Wait for end of conversion */
    if (HAL_ADC_PollForConversion(&hadc, ADC_TIMEOUT_MS) != HAL_OK)
    {
        HAL_ADC_Stop(&hadc);
        return 0xFFFFFFFFU;
    }
    u32CH0_ADC = HAL_ADC_GetValue(&hadc);

    if (HAL_ADC_PollForConversion(&hadc, ADC_TIMEOUT_MS) != HAL_OK)
    {
        HAL_ADC_Stop(&hadc);
        return 0xFFFFFFFFU;
    }
    u32CH1_ADC = HAL_ADC_GetValue(&hadc);

    /** Wait for end of conversion */
    HAL_ADC_Stop(&hadc);   /* it calls also ADC_Disable() */

    if (channel == ADC_CHANNEL_0)
    {
        return u32CH0_ADC;
    }
    else if (channel == ADC_CHANNEL_1)
    {
        return u32CH1_ADC;
    }

    return 0xFFFFFFFFU; /* invalid channel */
}

Please share your feedback on this.

Thanks.

Gyessine
ST Employee

Hello @shafin388 

Your ADC is configured in scan mode with two channels enabled, so each HAL_ADC_Start launches a sequence of two conversions. In your first version, you were reading only one channel per function, which means you were only taking one conversion result from the sequence and not necessarily the one you expected.

It looks like you corrected the acquisition flow in your second code: you always read both channels after starting the ADC, and then you return/print only the selected channel value. So the ADC scan is now fully consumed.

Based on that, I do not think the issue is related to the MCU category itself, but rather to the ADC configuration and how the conversion sequence was being read.
BR
Gyessine



To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hello Gyessine,

Correct. What ADC configuration should I use, so that I can read only one channel at a time instead of two channel after ADC start? And what should be flow for ADC start->poll->read->stop?

Thanks.

Hi Andrew,

Resolved issue of ADC read after doing changes into ADC init configuration.

Thanks.