1

I have a quite strange problem. I use the same micro in three projects. Two of them use HSI clock source, one HSE. Power is supplied exactly the same way. HSI ones go through the ADC calibration without any problems, HSE one gets stuck. Exactly the same initialisation procedure. ADC definitely works as I can read and write from the registers, I am getting ADC readings, but I cant go through the calibration

static inline void ADCCalibration(ADC_TypeDef *ADC) {
    uint32_t start = HAL_GetTick();
    ADC -> CR |= ADC_CR_ADCAL;
    while((ADC1 -> CR & ADC_CR_ADCAL)) {
        if((HAL_GetTick() - start) > ADC_CAL_TIMEOUT) {
            __BKPT();
        }
    }
}

__HAL_RCC_ADC12_CLK_ENABLE();
__HAL_RCC_ADC34_CLK_ENABLE();

ADC1 -> DIFSEL = 0;
ADC2 -> DIFSEL = 0;
ADC3 -> DIFSEL = 0;
ADC4 -> DIFSEL = 0;
while(ADC1 -> DIFSEL || ADC2 -> DIFSEL || ADC3 -> DIFSEL || ADC4 -> DIFSEL);
ADC1 -> CR &= ~(ADC_CR_ADVREGEN_Msk);
ADC1 -> CR |= ADC_CR_ADVREGEN_0;
ADC2 -> CR &= ~(ADC_CR_ADVREGEN_Msk);
ADC2 -> CR |= ADC_CR_ADVREGEN_0;
ADC3 -> CR &= ~(ADC_CR_ADVREGEN_Msk);
ADC3 -> CR |= ADC_CR_ADVREGEN_0;
ADC4 -> CR &= ~(ADC_CR_ADVREGEN_Msk);
ADC4 -> CR |= ADC_CR_ADVREGEN_0;
__ADC_Delay();

ADCCalibration(ADC1);
ADCCalibration(ADC2);
ADCCalibration(ADC3);
ADCCalibration(ADC4);

ADC1 -> CR |= ADC_CR_ADEN;
ADC2 -> CR |= ADC_CR_ADEN;
ADC3 -> CR |= ADC_CR_ADEN;
ADC4 -> CR |= ADC_CR_ADEN;
Bence Kaulics
  • 7,066
  • 7
  • 33
  • 63
0___________
  • 60,014
  • 4
  • 34
  • 74

3 Answers3

1

In you while loop, don't you mean:

while((ADC -> CR & ADC_CR_ADCAL))

rather than

while((ADC1 -> CR & ADC_CR_ADCAL))
Guillaume Michel
  • 1,189
  • 8
  • 14
  • 1
    Yes. Well spotted :) But it was not the issue. The problem was in the PLL & ADC clock settings. This micro require some additional configuration as the ADC has dual clock domain architecture. Now it works. – 0___________ May 09 '17 at 19:47
  • @0___________ Did you have to change the `CKMODE` bits in the `ADCx_CCR` register? – WBuck Jan 18 '21 at 03:19
1

maybe you could share what you did. Because I faced the same problem. What I did was to check if ARDY bit was set and also if the ADC is enabled (after reset for some reason it was enabled) and clear/disable them. Due to the ref. manual it is not allowed to start a calibration if ADC is enabled.

/* if ADRDY is set */
if((ADC3->ISR & ADC_ISR_ADRDY) == (ADC_ISR_ADRDY))
{
    ADC3->ISR |= (ADC_ISR_ADRDY); /* clear ADRDY */
}

/* if ADC3 is enabled */
if((ADC3->CR & ADC_CR_ADEN) == (ADC_CR_ADEN))
{
    ADC3->CR |= (ADC_CR_ADDIS); /* disable ADC3 */
}
Gautam
  • 2,597
  • 1
  • 28
  • 51
BanJoe
  • 11
  • 1
1

I also ran into this same issue on the STM32F303VC (Discovery board). Your comment on Guillaume's answer was the answer:

The problem was in the PLL & ADC clock settings. This micro require some additional configuration as the ADC has dual clock domain architecture

The reference manual had the following:

Dual clock domain architecture The dual clock-domain architecture means that each ADC clock is independent from the AHB bus clock. The input clock of the two ADCs (master and slave) can be selected between two different clock sources (see Figure 53: ADC clock scheme):

a) The ADC clock can be a specific clock source, named “ADCxy_CK (xy=12 or 34) which is independent and asynchronous with the AHB clock”. It can be configured in the RCC to deliver up to 72 MHz (PLL output). Refer to RCC Section for more information on generating ADC12_CK and ADC34_CK. To select this scheme, bits CKMODE[1:0] of the ADCx_CCR register must be reset.

b) The ADC clock can be derived from the AHB clock of the ADC bus interface, divided by a programmable factor (1, 2 or 4). In this mode, a programmable divider factor can be selected (/1, 2 or 4 according to bits CKMODE[1:0]). To select this scheme, bits CKMODE[1:0] of the ADCx_CCR register must be different from “00”.

When I originally tried to run the calibration the mode (value of the CKMODE bits) was 0.

This caused the calibration to never complete as I never configured RCC to generate an ADC12_CK clock.

To fix the issue I set the CKMODE bits to 2. That means the ADC clock will be derived from the AHB clock divided by 2.

WBuck
  • 5,162
  • 2
  • 25
  • 36
  • This question was asked 3y ago. Long time sorted:) – 0___________ Jan 18 '21 at 12:05
  • 2
    @0___________ Of course, but you never came back and posted the solution which is a cardinal sin. I posted my answer for anyone else in the same situation and who didn't see your comment.. Id either mark my answer as correct or post your solution for the benefit of others. – WBuck Jan 18 '21 at 14:26