Skip to main content
Visitor II
October 27, 2025
Solved

NUCLEO-H563ZI - ADC reading noise when input grounded

  • October 27, 2025
  • 6 replies
  • 508 views

Hello, I’m trying to perform ADC measurements with the STM32H563ZIT. I’ve shared my configuration settings from the .ioc file below. The ADC reading fluctuates by about ±40. When I short the ADC pin to GND, the reading varies between 0 and 30 instead of staying stable. I can’t get a constant value. What could be causing this issue?

static void MX_ADC1_Init(void)
{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN ADC1_Init 1 */

 /* USER CODE END ADC1_Init 1 */

 /** Common config
 */
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV10;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = ENABLE;
 hadc1.Init.ContinuousConvMode = DISABLE;
 hadc1.Init.NbrOfConversion = 1;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.DMAContinuousRequests = DISABLE;
 hadc1.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL;
 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc1.Init.OversamplingMode = ENABLE;
 hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
 hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
 hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
 hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_10;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC1_Init 2 */

 /* USER CODE END ADC1_Init 2 */

}

 

void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 /** Configure the main internal regulator output voltage
 */
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

 /** Initializes the RCC Oscillators according to the specified parameters
 * in the RCC_OscInitTypeDef structure.
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_CSI;
 RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 RCC_OscInitStruct.CSIState = RCC_CSI_ON;
 RCC_OscInitStruct.CSICalibrationValue = RCC_CSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLL1_SOURCE_CSI;
 RCC_OscInitStruct.PLL.PLLM = 1;
 RCC_OscInitStruct.PLL.PLLN = 50;
 RCC_OscInitStruct.PLL.PLLP = 2;
 RCC_OscInitStruct.PLL.PLLQ = 2;
 RCC_OscInitStruct.PLL.PLLR = 2;
 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1_VCIRANGE_2;
 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1_VCORANGE_WIDE;
 RCC_OscInitStruct.PLL.PLLFRACN = 0;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 /** Initializes the CPU, AHB and APB buses clocks
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
 |RCC_CLOCKTYPE_PCLK3;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV4;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure the programming delay
 */
 __HAL_FLASH_SET_PROGRAM_DELAY(FLASH_PROGRAMMING_DELAY_2);
}
    This topic has been closed for replies.
    Best answer by mƎALLEm

    Meanwhile, you didn't confirm which discovery you are using: STM32F4-Discoevery or STM32H573I-DK there is is big difference between both: note the same product, not the same architecture, not even the same ADC!

    Another hypothesis, it could be due to the Ethernet PHY on the Nucleo board. 

    Read this article: ADC value affected by ETH PHY 50 MHz from RMII interface

    From my side, I tested the following channels:

    - CH10 (PC0): worst case 5LSB

    - CH3 (PA6): worst case 2LSB

    - CH2 (PF11): worst case 2LSB

    - CH6 (PF12): worst case 2LSB

    So try channels far from ethernet signals. Try for example: CH6 (PF12).

    Attached the project I used for my tests. If you are still getting 40LSB, you need to remove all the non needed stuff including the potentiometer that we are seeing in the photo and keep only one wire to ground the ADC. Please use short wire. 

    6 replies

    Super User
    October 27, 2025

    Are you calibrating the ADC before using it (this is required).

    Custom board? Is VREF+/VDDA handled appropriately with decoupling caps? Show schematic.

    Iatik.1Author
    Visitor II
    October 27, 2025

    Yes, I'm calibrating it. I'm sharing the schematic file link.

     

    https://www.st.com/resource/en/schematic_pack/mb1404-h563zi-c01-schematic.pdf 

     /* USER CODE BEGIN 2 */
     __HAL_RCC_ADC_CLK_ENABLE();
     LL_ADC_EnableInternalRegulator(ADC1);
     HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
    
     /* USER CODE END 2 */
    
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     while (1)
     {
     /* USER CODE END WHILE */
    
     /* USER CODE BEGIN 3 */
    
    	 HAL_ADC_Start(&hadc1);
    	 if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
    	 {
    		 adcValue = HAL_ADC_GetValue(&hadc1);
    	 }
    	 HAL_ADC_Stop(&hadc1);

     

    Technical Moderator
    October 27, 2025

    Short wire length used? as it could be due to an antenna effect created by a long wire..

    Super User
    October 27, 2025

    Not real sure. You should definitely be getting better performance than +/- 15 counts at 12b resolution when using max sample rate and oversampling.

    Could be the way in which you're grounding the pin. How are you doing this exactly? Long wires can act as antennas.

    If you measure an internal channel such as VREFINT, do you see the same variation?

    Iatik.1Author
    Visitor II
    October 27, 2025

    I am measuring Vref and getting a very stable result. I am performing the same test with the discovery board, and the results are correct.

    Super User
    October 27, 2025

    as the others have said, it could be the way you're doing the "grounding".

    Posting a (or some) good, clear photo(s) may help to see what's going on ...

    Graduate II
    October 27, 2025

    Check the Nucleo's PCB layout and try some other ADC input.

    There are many signals going loooong ways to the connectors and other hardware via solder bridges.
    If you ground such a "bad" line without a capacitor close to the MCU input, there'll probably be some interference noise from the PCB.

    Iatik.1Author
    Visitor II
    October 27, 2025

    I'm getting the ground connection directly from the board. There are no problems with the connections. Long cables don't cause any problems on the Discovery board. I don't think it's the cable either. Do you have any real suggestions for a solution?

    Super User
    October 28, 2025

    No real suggestions, just wild unfounded theories about long wires being able to pick up noise I suppose. As you said, there are no problems with the hardware setup, so I'll move along.

    mƎALLEmAnswer
    Technical Moderator
    October 28, 2025

    Meanwhile, you didn't confirm which discovery you are using: STM32F4-Discoevery or STM32H573I-DK there is is big difference between both: note the same product, not the same architecture, not even the same ADC!

    Another hypothesis, it could be due to the Ethernet PHY on the Nucleo board. 

    Read this article: ADC value affected by ETH PHY 50 MHz from RMII interface

    From my side, I tested the following channels:

    - CH10 (PC0): worst case 5LSB

    - CH3 (PA6): worst case 2LSB

    - CH2 (PF11): worst case 2LSB

    - CH6 (PF12): worst case 2LSB

    So try channels far from ethernet signals. Try for example: CH6 (PF12).

    Attached the project I used for my tests. If you are still getting 40LSB, you need to remove all the non needed stuff including the potentiometer that we are seeing in the photo and keep only one wire to ground the ADC. Please use short wire.