Skip to main content
Graduate II
October 11, 2024
Solved

NUCLEO-G431KB, wrong values on ADC channel 4

  • October 11, 2024
  • 5 replies
  • 3209 views

Hello Forum,

I have an issue while reading the values from ADC. ADC1 is running in "continues scan convertion mode" using DMA and 5 ranks.

Here is ADC_Init function:

static void MX_ADC1_Init(void)
{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_MultiModeTypeDef multimode = {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_SYNC_PCLK_DIV4;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.GainCompensation = 0;
 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = DISABLE;
 hadc1.Init.ContinuousConvMode = ENABLE;
 hadc1.Init.NbrOfConversion = 5;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc1.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure the ADC multi-mode
 */
 multimode.Mode = ADC_MODE_INDEPENDENT;
 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_VREFINT;
 sConfig.Rank = ADC_REGULAR_RANK_2;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_1;
 sConfig.Rank = ADC_REGULAR_RANK_3;
 sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = ADC_REGULAR_RANK_4;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_4;
 sConfig.Rank = ADC_REGULAR_RANK_5;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC1_Init 2 */

 /* USER CODE END ADC1_Init 2 */

}

Then, here is my main() function:

int main(void)
{

 /* USER CODE BEGIN 1 */


 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */
 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_DAC1_Init();
 MX_I2C2_Init();
 MX_USB_Device_Init();
 MX_TIM17_Init();
 MX_CRC_Init();
 MX_ADC1_Init();
 /* USER CODE BEGIN 2 */
 if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
 {
	 Error_Handler();
 }

 if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_convertions, 5) != HAL_OK)
 {
	 Error_Handler();
 }



 HAL_DAC_Start(&hdac1, DAC1_CHANNEL_1);
 HAL_DAC_Start(&hdac1, DAC1_CHANNEL_2);
 HAL_TIM_Base_Start_IT(&htim17);

 AT24CXX_Init(hi2c2);
 load_configuration();
 init_spline();
 // load_default_configuration();

 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
	 timer_tasks_execute();

	 if (received_data)
	 {
		 process_tunerstudio();
		 received_data = false;
	 }
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

The variable adc_convertions is declared as uint32_t adc_convertions[5] = {0};

Issue:

If I apply the a voltage (2.15v) to PA1 and PA3, in adc_convertions array I get the ADC of 2620 for PA1 and 1531 for PA3. But, the both values shold be equal... The another ranks in adc_convertions array are correct.

  • I've tried to change a sample time for CHANNEL4 (= PA3), no success.
  • I removed SB1 and SB12 (because PA3 is connected to STLINK-V3E virtual c omport) , no success.
  • I've tried to map CHANNEL4 to different Rank, no success.

So, 'Ive no idea anymore...

Can you please help me?

Many thanks & regards,
Heinrich

    This topic has been closed for replies.
    Best answer by waclawek.jan

    > If I apply the a voltage (2.15v) to PA1 and PA3

    So, are PA1 and PA3 physically connected together?

    > I removed SB1 and SB12 (because PA3 is connected to STLINK-V3E virtual c omport)

    And did you connect SB14?

    JW

    5 replies

    Graduate II
    October 11, 2024

    Change your type to uint16_t instead of uint32_t 

     

    HeinrichAuthor
    Graduate II
    October 11, 2024

    Do you mean the type of adc_convertions[5]?

    Regards,
    Heinrich

    Graduate II
    October 12, 2024

    Yes ADC is 12bit then optimal result is 16bit half word DMA and uint16_t array.

    And for addressing array right syntax is adc_convertions or &adc_convertions[0] .

    Explorer
    October 11, 2024

    Instead:

    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_convertions, 5) != HAL_OK)

    try:

    if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)  adc_convertions, 5) != HAL_OK)

     

    And declaration of : uint32_t adc_convertions[5] = {0}; depends on DMA_word size, what we can't see, since no dma config provided.

    Super User
    October 12, 2024

    > If I apply the a voltage (2.15v) to PA1 and PA3

    So, are PA1 and PA3 physically connected together?

    > I removed SB1 and SB12 (because PA3 is connected to STLINK-V3E virtual c omport)

    And did you connect SB14?

    JW

    HeinrichAuthor
    Graduate II
    October 12, 2024

    Hi guys, first of all, thank you very much for help :)

    @MasterT:

    DMA is configured like this at the moment:

    Heinrich_0-1728739610358.png

    Since STM32 is a 32-bit MCU, WORD means uint32_t, I think... It is correct?

    @waclawek.jan 

    Yes, PA1 and PA3 are connected together. Not directly on Nucleo, but on carrier board. The is a voltage divider (5v to 3.3), then buffer and then NUCLEO. AI've applied 3.3v from NUCLEO to both input pins, after voltage diviers and buffers, I get 2.15v on BOTH pins of NUCLEO. So, the hardware should be okay, because the get the same voltage.

    No, SB15 is still default, so not "installed".

    @MM..1Okay, I've removed & , the DMA is configured as word, not half-word.

    What I've done:

    • Remove the & in if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *) adc_convertions, 5) != HAL_OK)
    • Changed uint32_t to uint16_t.

    Result:

    • CHANNEL1 (adc_convertions[0]) says 2620, correct.
    • CHANNEL4 (adc_convertions[1]) says 0, normal since SB14 is open...

    I will close SB14 a bit later and test it :)

    Explorer
    October 12, 2024

    If DMA configured as Word_Peripheral- Word_Memory, than 

    uint32_t adc_convertions[5] = {0};  or int32_t adc_convertions[5] = {0};

    correct declaration. 

    For Halfword_Peripheral- Halfword_Memory, than 

    uint16_t adc_convertions[5] = {0};  or int16_t adc_convertions[5] = {0}; 

    HeinrichAuthor
    Graduate II
    October 12, 2024

    Okay, then it was correct.

    I've changed them back to uint32_t adc_convertions[5] = {0};

    and:

    • adc_convertions[0] says 2621, correct
    • adc_convertions[1] says 1543, wrong

    I'll test with SB14 closed today evening.

    Regards,
    Heinrich

    HeinrichAuthor
    Graduate II
    October 12, 2024

    So, now I've closed SB14 and started a new project, adc + dma only.

    DMA Config:

    Heinrich_0-1728751558532.png

    With buffer for DMA data:

     

    uint16_t adc_values[2] = {0};

     

    And DMA start:

     

     if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *) adc_values, 2) != HAL_OK)
     {
    	 Error_Handler();
     }

     

    ADC config:

    Heinrich_1-1728751603109.png

    ADC config 2nd:

    Heinrich_2-1728751629736.png

    Here is the whole code from main.c:

     

    /* USER CODE BEGIN Header */
    /**
     ******************************************************************************
     * @file : main.c
     * @brief : Main program body
     ******************************************************************************
     * @attention
     *
     * Copyright (c) 2024 STMicroelectronics.
     * All rights reserved.
     *
     * This software is licensed under terms that can be found in the LICENSE file
     * in the root directory of this software component.
     * If no LICENSE file comes with this software, it is provided AS-IS.
     *
     ******************************************************************************
     */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    ADC_HandleTypeDef hadc1;
    DMA_HandleTypeDef hdma_adc1;
    
    /* USER CODE BEGIN PV */
    
    uint16_t adc_values[2] = {0};
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    static void MX_GPIO_Init(void);
    static void MX_DMA_Init(void);
    static void MX_ADC1_Init(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    
    /* USER CODE END 0 */
    
    /**
     * @brief The application entry point.
     * @retval int
     */
    int main(void)
    {
    
     /* USER CODE BEGIN 1 */
    
     /* USER CODE END 1 */
    
     /* MCU Configuration--------------------------------------------------------*/
    
     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
     HAL_Init();
    
     /* USER CODE BEGIN Init */
    
     /* USER CODE END Init */
    
     /* Configure the system clock */
     SystemClock_Config();
    
     /* USER CODE BEGIN SysInit */
    
     /* USER CODE END SysInit */
    
     /* Initialize all configured peripherals */
     MX_GPIO_Init();
     MX_DMA_Init();
     MX_ADC1_Init();
     /* USER CODE BEGIN 2 */
     if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *) adc_values, 2) != HAL_OK)
     {
    	 Error_Handler();
     }
    
     /* USER CODE END 2 */
    
     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
    
     uint32_t blah = 0;
     while (1)
     {
    	 HAL_Delay(500);
    	 blah++;
     /* USER CODE END WHILE */
    
     /* USER CODE BEGIN 3 */
     }
     /* USER CODE END 3 */
    }
    
    /**
     * @brief System Clock Configuration
     * @retval None
     */
    void SystemClock_Config(void)
    {
     RCC_OscInitTypeDef RCC_OscInitStruct = {0};
     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
     /** Configure the main internal regulator output voltage
     */
     HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
    
     /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
     RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
     RCC_OscInitStruct.HSEState = RCC_HSE_ON;
     RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
     RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
     RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
     RCC_OscInitStruct.PLL.PLLN = 24;
     RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
     RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
     RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
     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_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
     {
     Error_Handler();
     }
    }
    
    /**
     * @brief ADC1 Initialization Function
     * @PAram None
     * @retval None
     */
    static void MX_ADC1_Init(void)
    {
    
     /* USER CODE BEGIN ADC1_Init 0 */
    
     /* USER CODE END ADC1_Init 0 */
    
     ADC_MultiModeTypeDef multimode = {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_SYNC_PCLK_DIV4;
     hadc1.Init.Resolution = ADC_RESOLUTION_12B;
     hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
     hadc1.Init.GainCompensation = 0;
     hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
     hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
     hadc1.Init.LowPowerAutoWait = DISABLE;
     hadc1.Init.ContinuousConvMode = ENABLE;
     hadc1.Init.NbrOfConversion = 2;
     hadc1.Init.DiscontinuousConvMode = DISABLE;
     hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
     hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
     hadc1.Init.DMAContinuousRequests = ENABLE;
     hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
     hadc1.Init.OversamplingMode = DISABLE;
     if (HAL_ADC_Init(&hadc1) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Configure the ADC multi-mode
     */
     multimode.Mode = ADC_MODE_INDEPENDENT;
     if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Configure Regular Channel
     */
     sConfig.Channel = ADC_CHANNEL_2;
     sConfig.Rank = ADC_REGULAR_RANK_1;
     sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5;
     sConfig.SingleDiff = ADC_SINGLE_ENDED;
     sConfig.OffsetNumber = ADC_OFFSET_NONE;
     sConfig.Offset = 0;
     if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
     {
     Error_Handler();
     }
    
     /** Configure Regular Channel
     */
     sConfig.Channel = ADC_CHANNEL_4;
     sConfig.Rank = ADC_REGULAR_RANK_2;
     if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
     {
     Error_Handler();
     }
     /* USER CODE BEGIN ADC1_Init 2 */
     if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
     {
    	 Error_Handler();
     }
    
     /* USER CODE END ADC1_Init 2 */
    
    }
    
    /**
     * Enable DMA controller clock
     */
    static void MX_DMA_Init(void)
    {
    
     /* DMA controller clock enable */
     __HAL_RCC_DMAMUX1_CLK_ENABLE();
     __HAL_RCC_DMA1_CLK_ENABLE();
    
     /* DMA interrupt init */
     /* DMA1_Channel1_IRQn interrupt configuration */
     HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
     HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
    
    }
    
    /**
     * @brief GPIO Initialization Function
     * @PAram None
     * @retval None
     */
    static void MX_GPIO_Init(void)
    {
     GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* USER CODE BEGIN MX_GPIO_Init_1 */
    /* USER CODE END MX_GPIO_Init_1 */
    
     /* GPIO Ports Clock Enable */
     __HAL_RCC_GPIOF_CLK_ENABLE();
     __HAL_RCC_GPIOA_CLK_ENABLE();
     __HAL_RCC_GPIOB_CLK_ENABLE();
    
     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    
     /*Configure GPIO pin : LD2_Pin */
     GPIO_InitStruct.Pin = LD2_Pin;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
     GPIO_InitStruct.Pull = GPIO_NOPULL;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
     HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
    
    /* USER CODE BEGIN MX_GPIO_Init_2 */
    /* USER CODE END MX_GPIO_Init_2 */
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    /**
     * @brief This function is executed in case of error occurrence.
     * @retval None
     */
    void Error_Handler(void)
    {
     /* USER CODE BEGIN Error_Handler_Debug */
     /* User can add his own implementation to report the HAL error return state */
     __disable_irq();
     while (1)
     {
     }
     /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef USE_FULL_ASSERT
    /**
     * @brief Reports the name of the source file and the source line number
     * where the assert_param error has occurred.
     * @PAram file: pointer to the source file name
     * @PAram line: assert_param error line source number
     * @retval None
     */
    void assert_failed(uint8_t *file, uint32_t line)
    {
     /* USER CODE BEGIN 6 */
     /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
     /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */

     

    Result:

    • adc_convertions[0] says 2622, correct
    • adc_convertions[1] says 2621, correct

    I think the point with SB14 was the solution...

    Now it fine and all the values are correct.

    Thank you very much!