2022-10-30 06:42 AM
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!
Solved! Go to Solution.
2022-10-30 08:08 AM
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!
2022-10-30 07:14 AM
did you calibrate ADC ? need it first... see:
so: first calibrate, wait, enable , wait , -> ready. set ADC channel, start ADC.
2022-10-30 07:19 AM
Read out and check/post ADC registers content.
Did you enable ADC in RCC?
JW
2022-10-30 07:25 AM
Yes, before calling those methods. I checked in the registers if it was set before calling the methods
2022-10-30 07:34 AM
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
2022-10-30 07:54 AM
enable ADC power - ok. and enable clock ?
2022-10-30 07:56 AM
yep, the clock is configured for the ADC
2022-10-30 08:08 AM
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!
2022-10-30 08:09 AM
looking at this i tried to divide by 2 the clock frequency of the ADC and it worked. So thanks a lot!
2023-01-03 09:11 AM
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