Skip to main content
JMart.13
Associate III
October 30, 2022
Solved

ADC register ADRDY never sets when I enable the ADC, so it keeps waiting there to start STM32F303RBT6

  • October 30, 2022
  • 11 replies
  • 6100 views

Hi all,

I have this problem. I want to start the ADC of my microcontroller, and following the reference manual it says I have to wait until the ADRDY register is set by the hardware to continue and make conversions, but that register never sets. This is my code:

This function enables the DMA fot the ADC

void DMA_Init(ADC_TypeDef * adc, DMA_Channel_TypeDef * dma_ch, std::uint16_t * buffer, std::uint32_t buffer_length,std::uint8_t length){
 
	adc->CFGR |= ADC_CFGR_CONT; 
	adc->CFGR |= ADC_CFGR_DMAEN | ADC_CFGR_DMACFG;
	adc->SMPR1 |= (7U << 3U) | (7U << 6U); //max sampling rate 
	
			
	dma_ch->CPAR = (std::uint32_t)(&adc->DR); 
	dma_ch->CMAR = (std::uint32_t)(buffer); 
	dma_ch->CNDTR = buffer_length; 	
	dma_ch->CCR |= DMA_CCR_EN;				
			
			
	Enable_regulator(adc);
	Enable(adc); 
	Calib(adc); 
	Enable(adc); 
			
}

So these are the enable regulator and enable functions:

void Enable_regulator(ADC_TypeDef * adc){ 
	adc->CR &= ~(ADC_CR_ADVERGEN_CLEAR); 
	adc->CR |= ADC_CR_ADVERGEN_ENABLE; 
	utils::delay::us(30); 
}
 
 
void Enable(ADC_TypeDef * adc){
	adc->CR |= ADC_CR_ADEN; 
	while(!(adc->ISR & ADC_ISR_ADRDY)){}
}

The enable regulator works perfectly. But the enable function keeps waiting forever. Any help would be great.

Thanks!

This topic has been closed for replies.
Best answer by JMart.13

OK, i had to configure the ADC12_COMMON_CLOCK with a prescaler of 2 to work:

ADC12_COMMON->CCR |= (1U << 17U);

Thanks for the help!

11 replies

AScha.3
Super User
October 30, 2022

did you calibrate ADC ? need it first... see:

0693W00000VORAjQAP.pngso: first calibrate, wait, enable , wait , -> ready. set ADC channel, start ADC.

0693W00000VORAoQAP.png

If you feel a post has answered your question, please click on " Best Answer ".
JMart.13
JMart.13Author
Associate III
October 30, 2022

Hum whenever I need an operation of waiting for the hardware to set those bits it just freezes :\ since the calibration needs to wait until ADC_CR_ADCAL != 0

void Calib(ADC_TypeDef * adc){
	 
	adc->CR &= ~ADC_CR_ADCALDIF; 
	adc->CR |= ADC_CR_ADCAL; 
			
	while((adc->CR & ADC_CR_ADCAL) != 0){}
}

even disabling the ADC freeze at waiting

waclawek.jan
Super User
October 30, 2022

Read out and check/post ADC registers content.

Did you enable ADC in RCC?

JW

JMart.13
JMart.13Author
Associate III
October 30, 2022

Yes, before calling those methods. I checked in the registers if it was set before calling the methods

AScha.3
Super User
October 30, 2022

enable ADC power - ok. and enable clock ?

0693W00000VORDnQAP.png

If you feel a post has answered your question, please click on " Best Answer ".
JMart.13
JMart.13Author
Associate III
October 30, 2022

yep, the clock is configured for the ADC

JMart.13
JMart.13AuthorBest answer
Associate III
October 30, 2022

OK, i had to configure the ADC12_COMMON_CLOCK with a prescaler of 2 to work:

ADC12_COMMON->CCR |= (1U << 17U);

Thanks for the help!

unsigned_char_array
Lead III
January 3, 2023

I had the same problem with the STM32L431RCT6. ADRDY bit in ISR was never set after enabling. This caused the DMA to keep reading zeros from the ADC. It didn't work with prescaler set to 32 or 64, but it did sometimes work with 16. Slightly reordering the code, adding some delays or adding breakpoints at certain places would also affect this issue and either fix it or cause it to happen again. My workaround was to simply keep trying to set ADEN. Not pretty, but it works for all clock settings now!

// doesn't always work directly after calibration, so keep trying
while(LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0) 
{
	LL_ADC_Enable(ADC1);
}

Edit: ST has a define LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES. It doesn't use this delay in generated code. But if you delay this number of ADC cycles after calibration the enable seems to work. But you still need to wait for the active flag to turn high before you can use the ADC. So I kept the code just in case

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."
waclawek.jan
Super User
January 3, 2023

@Community member​ 

Thanks for reporting this.

Please, in all posts relating to ADC, tell us the STM32 model, as ADC is probably the most varying peripheral across STM32 models.

No related erratum?

> It didn't work with prescaler set to 32 or 64, but it did sometimes work with 16.

So, what was exactly the mcu/APB and ADC clock setting?

It sounds, that this is the key. ST's grip on the cross-clock-domain issues in peripherals is not stellar.

JW

unsigned_char_array
Lead III
January 4, 2023

> tell us the STM32 model

Done, I added STM32L431RCT6 to my posts.

> No related erratum?

No. The chapter about ADC had only the following issues:

  1. Writing ADCx_JSQR when JADCSTART and JQDIS are set might lead to incorrect behavior
  2. Wrong ADC result if conversion done late after calibration or previous conversion
  3. Spurious temperature measurement due to spike noise
  4. Selected external ADC inputs unduly clamped to VDD when all analog peripherals are disabled

None of them apply to this situation.

> So, what was exactly the mcu/APB and ADC clock setting?

Currently CPU=80MHz, ADC=1.25MHz. But it works for 2.5MHz and 5MHz as well. I haven't tested other frequencies, but if I go higher I cannot sample the temperature sensor slower than the minimum of 120us from the datasheet.

> It sounds, that this is the key. ST's grip on the cross-clock-domain issues in peripherals is not stellar.

I had my suspicion it was due to synchronization between MCU core and/or DMA with the ADC. I didn't know it was called Clock domain crossing (CDC). It sounds like something very fundamental that a manufacturer of MCUs should know how to avoid! The headerfile does have a define LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES, but it isn't used in any generated code!

"Kudo posts if you have the same problem and kudo replies if the solution works.Click ""Accept as Solution"" if a reply solved your problem. If no solution was posted please answer with your own."