Skip to main content
Associate III
June 14, 2026
Question

STM32G4 - ADC injected discontinuous mode issue - Hard bit setting required

  • June 14, 2026
  • 4 replies
  • 45 views

Hi,

I am trying to perform injected conversion of two channels in ADC1 (STM32G431x), and I wish to trigger them in discontinuous mode. The ScanConvMode is enabled and the discontinuous mode for injected measurement is also set (injectedDiscontinuousConvMode = ENABLE). However, the conversion still happens continuously. 

 

I had to hard set the bit (SET_BIT(ADC1->CFGR, ADC_CFGR_JDISCEN)) to make it work in discontinuous mode.Any help here will be appreciated! Thanks.

4 replies

ST Technical Moderator
June 15, 2026


Hello ​@mechatron 
Just to verify
can you check or share with us your  ADC configuration
I don’t know your exact ADC needed configuration
But I tried a simple ADC example using injected discontinious mode and found out that the bit is being set like he should be
 

I’im gonna share parts of my code so you can compare it with yours maybe you will find some differences:

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;

UART_HandleTypeDef huart3;

/* USER CODE BEGIN PV */
uint32_t adc_inj_ch2 = 0;
uint32_t adc_inj_ch3 = 0;
char msg[100];
/* USER CODE END PV */

/* USER CODE BEGIN 0 */
int _write(int file, char *ptr, int len)
{
HAL_UART_Transmit(&huart3, (uint8_t*)ptr, len, HAL_MAX_DELAY);
return len;
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED, ADC_SINGLE_ENDED) != HAL_OK)
{
Error_Handler();
}


/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (HAL_ADCEx_InjectedStart(&hadc1) != HAL_OK)
{
Error_Handler();
}

if (HAL_ADCEx_InjectedPollForConversion(&hadc1, 100) == HAL_OK)
{
adc_inj_ch2 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1);
printf("CH2=%lu\r\n", adc_inj_ch2);
}

HAL_Delay(500);
}
/* USER CODE END 3 */
}
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};

/* USER CODE BEGIN ADC1_Init 1 */

/* USER CODE END ADC1_Init 1 */

/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
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 = ENABLE;
hadc1.Init.NbrOfDiscConversion = 1;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.Oversampling.Ratio = 1;
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();
}

/** Disable Injected Queue
*/
HAL_ADCEx_DisableInjectedQueue(&hadc1);

/** Configure Injected Channel
*/
sConfigInjected.InjectedChannel = ADC_CHANNEL_2;
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_810CYCLES_5;
sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED;
sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE;
sConfigInjected.InjectedOffset = 0;
sConfigInjected.InjectedNbrOfConversion = 1;
sConfigInjected.InjectedDiscontinuousConvMode = ENABLE;
sConfigInjected.AutoInjectedConv = DISABLE;
sConfigInjected.QueueInjectedContext = DISABLE;
sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START;
sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_NONE;
sConfigInjected.InjecOversamplingMode = DISABLE;
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */

}

Here is  the ADC .IOC file config, does it comply with your needs?  

However i will admit that i found a weird behavior with 

  sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;

always generated as disabled no matter how it was configured in STM32CubeMX, I will check it
I hope this will help you troubleshoot your issue root cause for now
BR
Gyessine

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question.
mechatronAuthor
Associate III
June 16, 2026

Hi ​@Gyessine ,

Thank you for the response. For the discontinuous mode to work, the ScanConvMode must be enabled, right? From your code segment, it does not seem like it. I will try to see if the JDISCEN bit is getting set normally, but I guess not.

 

Moreover, I require the discontinuous mode since there is a regular measurement ongoing. I do not wish to disturb its timing, hence preferred the discontinuous one.

ST Technical Moderator
June 17, 2026

Hello ​@mechatron 
In the provided example, only one channel is enabled. Therefore, ScanConvMode is not activated. If multiple channels are needed in this case, enable it.
BR
Gyessine

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question.
mechatronAuthor
Associate III
June 18, 2026

Hi ​@Gyessine ,

 

As I mentioned in my initial description, I am trying to establish injected conversion for two channels, which is interfering with a regular ongoing measurement on that ADC. Moreover, for discontinuous, I see the following comment. Is this false, then?  That ScanConvMode shall be enabled only if multiple channels are involved, and not to enable just the DiscontinuousConvMode (As mentioned in the image below)?

 

I am providing the code section for the ADC config as well. Let me know if there is something wrong, that prevents the DiscontinuousConvMode from getting enabled.

 

ADC_HandleTypeDef hadc1 = {
.Instance = ADC1,
.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2,
.Init.Resolution = ADC_RESOLUTION_12B,
.Init.DataAlign = ADC_DATAALIGN_RIGHT,
.Init.ScanConvMode = ADC_SCAN_ENABLE,
.Init.EOCSelection = ADC_EOC_SINGLE_CONV,
.Init.LowPowerAutoWait = DISABLE,
.Init.ContinuousConvMode = DISABLE,
.Init.NbrOfConversion = 1,
.Init.DiscontinuousConvMode = DISABLE,
.Init.NbrOfDiscConversion = 0,
.Init.ExternalTrigConv = ADC_TRIGGER,
.Init.ExternalTrigConvEdge = ADC_TRIGGER_EDGE,
.Init.DMAContinuousRequests = ENABLE,
.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN,
.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL,
.Init.OversamplingMode = DISABLE,
.Init.Oversampling = {.Ratio = 0,
.RightBitShift = 0,
.TriggeredMode = 0,
.OversamplingStopReset = 0},
.Init.GainCompensation = 0,
};

ADC_CONST AdcInjectedGpioPinCfg_t adcV1CheckCfg = {
.pin = {.port = GPIOA, .pin = GPIO_PIN_0},
.hadc = &hadc1,
.channel = {
.InjectedChannel = ADC_CHANNEL_1,
.InjectedRank = ADC_INJECTED_RANK_1,
.InjectedSamplingTime = ADC_INJECTED_SAMPLE_TIME,
.InjectedSingleDiff = ADC_SINGLE_ENDED,
.InjectedOffsetNumber = ADC_OFFSET_NONE,
.InjectedOffset = 0,
.InjectedNbrOfConversion = NBR_INJECTED_ADC,
.InjectedDiscontinuousConvMode = ENABLE,
.AutoInjectedConv = DISABLE,
.QueueInjectedContext = DISABLE,
.ExternalTrigInjecConv = ADC_INJECTED_TRIGGER,
.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING,
.InjecOversamplingMode = DISABLE
}};

ADC_CONST AdcInjectedGpioPinCfg_t adcV2CheckCfg = {
.pin = {
.port = GPIOB,
.pin = GPIO_PIN_14},
.hadc = &hadc1,
.channel = {.InjectedChannel = ADC_CHANNEL_5,
.InjectedRank = ADC_INJECTED_RANK_2,
.InjectedSamplingTime = ADC_INJECTED_SAMPLE_TIME}};