cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F072R8 ADC EOC is not complete

ab_nurd
Associate II

Hello,

I am using ADC1 of STM32F072R8 to measure temperature from sensor. The ADC is being used in continuous mode. For some historical reasons I still use standard peripheral library. Here is my code:

void Temperature_ADC_Init()
 
{
 
    GPIO_InitTypeDef gpioInitStructure;
 
    NVIC_InitTypeDef nvicInitStructure;
 
    ADC_InitTypeDef temperature_adc;
 
 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
 
    ADC_ClockModeConfig(ADC1, ADC_ClockMode_SynClkDiv4);
 
 
    gpioInitStructure.GPIO_Pin = TEMP_SENSE_PIN;
 
    gpioInitStructure.GPIO_Mode = GPIO_Mode_AN;
 
    gpioInitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
    gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz;
 
    gpioInitStructure.GPIO_OType = GPIO_OType_PP;
 
    GPIO_Init( TEMP_SENSE_PORT, &gpioInitStructure );
 
 
    temperature_adc.ADC_Resolution = ADC_Resolution_10b;
 
    temperature_adc.ADC_ContinuousConvMode = ENABLE;
 
    temperature_adc.ADC_DataAlign = ADC_DataAlign_Right;
 
    temperature_adc.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
 
    temperature_adc.ADC_ScanDirection = ADC_ScanDirection_Backward;
 
    ADC_Init(ADC1, &temperature_adc);
 
 
    ADC_ChannelConfig(ADC1, ADC_Channel_10, ADC_SampleTime_239_5Cycles);
 
 
    //Enable address ready and end of conversion interrupt
 
    ADC_ClearITPendingBit(ADC1, ADC_IT_ADRDY);
 
    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
 
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
 
    ADC_ITConfig(ADC1, ADC_IT_ADRDY, ENABLE);
 
 
    //Enable ADC1 interrupt
 
    nvicInitStructure.NVIC_IRQChannel = ADC1_COMP_IRQn;
 
    nvicInitStructure.NVIC_IRQChannelPriority = 3;
 
    nvicInitStructure.NVIC_IRQChannelCmd = ENABLE;
 
    NVIC_Init(&nvicInitStructure);
 
 
    ADC_GetCalibrationFactor(ADC1); 
    /* As per errata sheet, there shall be at least 4 cycle wait after calibration is done. */
    for (i = 0; i < 10; i++);
 
 
    ADC_Cmd(ADC1, ENABLE);
 
}
 
 
void ADC1_IRQHandler (void)
 
{
 
    ADC_ISR_Handler();
 
}
 
 
void ADC_ISR_Handler()
 
{
 
    //Check for end of conversion
 
    if (ADC_GetITStatus(ADC1, ADC_IT_EOC))
 
    {
 
        //Clear interrupt bit
 
        ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
 
        adc_value = ADC_GetConversionValue(ADC1);
 
    }
 
    else if (ADC_GetITStatus(ADC1, ADC_IT_ADRDY))
 
    {
 
        //Clear interrupt bit
 
        ADC_ClearITPendingBit(ADC1, ADC_IT_ADRDY);
 
        adc_ready = 1;
 
    }
 
}
 
int main()
{
   Temperature_ADC_Init();
 
    while(1)
    {
                /* Check if ADC is ready and start conversion */
		if (adc_ready && !adc_conv_started) {
			ADC_StartOfConversion(ADC1);
			adc_conv_started = 1;
		}
    }
 
    return 0;
}

Apart from ADC ISR, there is also USB ISR active but has higher priority than ADC.

As per errata sheet of STM32F072R8, ADEN bit cannot be set immediately after the ADC calibration. Therefore there is delay added after call of calibration function.

Although I get ADC ready and hence corresponding interrupt and start ADC conversion process, the ADC conversion is never complete. I do not get EOC interrupt. After some trials (reseting of microcontroller and checking), EOC works but it is very sporadic.

I had also tried ADC using polling method instead of interrupt. But there too, it waited for EOC flag all time and it was never set.

How could I get this ADC EOC running?

Thanks.

1 REPLY 1
ab_nurd
Associate II

In Temperature_ADC_Init function, afer ADC_Init function was called, I saw some incorrect values in registers of ADC while debugging, don't know why. I manually wrote config register and then EOC ISR and its flag started working.

ADC1->CFGR1 = 0x4001000C;