Skip to main content
Explorer
November 15, 2025
Solved

STM32G4 Dual Injected Simultaneous Mode ADC2 Returns 0

  • November 15, 2025
  • 1 reply
  • 221 views

I'm using STM32G474 with dual ADC injected simultaneous mode. İndividual ADC injected mode works ok.

ADC1 is triggered by TIM1 Channel 4 and the interrupt is firing correctly, but ADC2 always returns zero.

 

Questions:

  1. Why does ADC2->JDR1 always return 0 in dual injected simultaneous mode?
  2. Is it correct that HAL_ADCEx_InjectedStart_IT(&hadc2) returns HAL_ERROR in dual mode?

You can see my ADC1 and ADC2 configuration.

void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
 if (hadc->Instance == ADC1) {

 	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
 	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

 adc1 = ADC1->JDR1;

 adc2 = ADC2->JDR1;
 }

}

 

static void MX_ADC1_Init(void)
{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_MultiModeTypeDef multimode = {0};
 ADC_InjectionConfTypeDef sConfigInjected = {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_DISABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc1.Init.LowPowerAutoWait = DISABLE;
 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.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_DUALMODE_INJECSIMULT;
 multimode.DMAAccessMode = ADC_DMAACCESSMODE_DISABLED;
 multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;
 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Injected Channel
 */
 sConfigInjected.InjectedChannel = ADC_CHANNEL_2;
 sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
 sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5;
 sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
 sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
 sConfigInjected.InjectedOffset = 0;
 sConfigInjected.InjectedNbrOfConversion = 1;
 sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
 sConfigInjected.AutoInjectedConv = DISABLE;
 sConfigInjected.QueueInjectedContext = DISABLE;
 sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJEC_T1_CC4;
 sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;
 sConfigInjected.InjecOversamplingMode = DISABLE;
 if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_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 */

}

/**
 * @brief ADC2 Initialization Function
 * None
 * @retval None
 */
static void MX_ADC2_Init(void)
{

 /* USER CODE BEGIN ADC2_Init 0 */

 /* USER CODE END ADC2_Init 0 */

 ADC_InjectionConfTypeDef sConfigInjected = {0};

 /* USER CODE BEGIN ADC2_Init 1 */

 /* USER CODE END ADC2_Init 1 */

 /** Common config
 */
 hadc2.Instance = ADC2;
 hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
 hadc2.Init.Resolution = ADC_RESOLUTION_12B;
 hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc2.Init.GainCompensation = 0;
 hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
 hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc2.Init.LowPowerAutoWait = DISABLE;
 hadc2.Init.ContinuousConvMode = DISABLE;
 hadc2.Init.NbrOfConversion = 1;
 hadc2.Init.DiscontinuousConvMode = DISABLE;
 hadc2.Init.DMAContinuousRequests = DISABLE;
 hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 hadc2.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc2) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure Injected Channel
 */
 sConfigInjected.InjectedChannel = ADC_CHANNEL_9;
 sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
 sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5;
 sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
 sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
 sConfigInjected.InjectedOffset = 0;
 sConfigInjected.InjectedNbrOfConversion = 1;
 sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;
 sConfigInjected.AutoInjectedConv = DISABLE;
 sConfigInjected.QueueInjectedContext = DISABLE;
 sConfigInjected.InjecOversamplingMode = DISABLE;
 if (HAL_ADCEx_InjectedConfigChannel(&hadc2, &sConfigInjected) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN ADC2_Init 2 */

 /* USER CODE END ADC2_Init 2 */

}

 

    This topic has been closed for replies.
    Best answer by Saket_Om

    Hello @batuhanky 

    In your case ADC2 should be started before ADC1.  

    1 reply

    Saket_OmAnswer
    Technical Moderator
    November 19, 2025

    Hello @batuhanky 

    In your case ADC2 should be started before ADC1.