Skip to main content
EThom.3
Senior II
January 20, 2026
Solved

What can keep the ADC from finishing a conversion? (STM32G474)

  • January 20, 2026
  • 1 reply
  • 289 views

I am trying to complete one – just one – ADC conversion without using DMA. This is sort of a one-off sampling after power-on, and subsquently the regular sequence conversion with DMA is to take over. But I don't get that far.

I'm trying to sample ADC1 channel 15, but never get a high EOC flag. To be absolutely certain about how the ADC is set up, I've read these register values via STM32CubeProgrammer:

ADC1_CFGR = 0x80000000

In short: Injected queue disabled; contiuous and discontinuous modes off; hardware trigger disabled; DMA disabled.

ADC1_CFGR2 = 0

In short: BULB disabled; gain compensation disabled; oversampling disabled.

ADC1_SMPR2 = 0x0003E000

In short: Channel 15 sampling time 640.5 clock cycles; channel 14 sampling time 247.5 clock cycles.

ADC1_SQR1 = 0x081C23C0

In short: First conversion channel is 15. Number of conversions is 1. All other bits should be irrelevant.

ADC1_CR = 0x10000005

In short: ADC voltage regulator is enabled; ADC is enabled: ADC is converting (apparently)

ADC1_ISR = 1

In short: ADC is ready. EOC never changes to 1.

Just to check that the ADC clock is enabled, I read the appropriate RCC register:

RCC_AHB2ENR = 0x0003607F

In short: All ADC clocks are enabled.

Has the IO pin (PB0) even be set to be an analog input?

GPIOB_MODER = 0xAAFEAA7F

Yes, the IO pin is configured as an analog input.

DMA1_CCR7 = 0x00000580

In short: The DMA channel is disabled, as I intend not to use it for this conversion.

 

A condensed version of the ADC code is here:

 ADCHandle->Instance->CR |= ADC_CR_ADCAL; // Start calibration

 ADCHandle->Instance->SMPR2 |= ADC_SMPR2_SMP15_Msk; // Set 640.5 ADC clock cycles for channel 15.
 ADCHandle->Instance->SQR1 = (ADCHandle->Instance->SQR1 & ~(ADC_SQR1_SQ1_Msk | ADC_SQR1_L_Msk)) | (15 << ADC_SQR1_SQ1_Pos); // Set channel 15 and only one conversion
 ADCHandle->Instance->CFGR = ADC_CFGR_JQDIS; // Disable injected queue and DMA
 ADCHandle->Instance->CFGR2 = 0;

 while (ADCHandle->Instance->CR & ADC_CR_ADCAL); // Wait for calibration to finish

 ADCHandle->Instance->CR |= ADC_CR_ADEN; // ADC enable
 ADCHandle->Instance->ISR = ADC_ISR_EOS | ADC_ISR_EOC; // Reset EOS and EOC flags
 ADCHandle->Instance->CR |= ADC_CR_ADSTART; // ADC start conversion

 while (!(ADCHandle->Instance->ISR & ADC_ISR_EOC)); // Wait for conversion to finish

My program gets stuck in the last while loop, as EOC never becomes 1.

ADCHandle is a pointer to hadc1, which is declared in main.c. I could have used ADC1 diectly, but I initially intended to make the function more portable. In any case, the registers get the intended values, so this shouldn't be the issue..

If I skip this piece of code, the DMA-based conversions run fine. I clearly have access to the ADC when I set it up with DMA – just not without it. I am currently considering using DMA for this just to make something work, but I would rather figure out what I am doing wrong.

Can someone see if I've missed something obvious? One of more crucial registers I haven't considered? Any help would be greatly appreciated.

Edit: Corrected name of RCC register.

Best answer by TDK

Wait until calibration is done before configuring the ADC.

You're not really following the RM procedure for how to enable the ADC.

TDK_0-1768922146453.png

 

1 reply

TDK
TDKBest answer
Super User
January 20, 2026

Wait until calibration is done before configuring the ADC.

You're not really following the RM procedure for how to enable the ADC.

TDK_0-1768922146453.png

 

"If you feel a post has answered your question, please click ""Accept as Solution""."
EThom.3
EThom.3Author
Senior II
January 20, 2026

Thanks! I had a hunch that I had overlooked something relatively simple.

This made a huge difference:

 

 ADCHandle->Instance->ISR = ADC_ISR_ADRDY; // Clear ADRDY flag
 ADCHandle->Instance->CR |= ADC_CR_ADEN; // ADC enable
 while (!(ADCHandle->Instance->ISR & ADC_ISR_ADRDY)); // Wait for ADC ready

 

Much appreciated! :)