cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F030 - ADC1 interrupt at EOC doesn't work! (solved)

mojtahedzadeh
Associate II
Posted on July 17, 2016 at 22:42

I have a micro-controller board based on STM32F030F4P6. I have written a program to read a channel of Analog to Digital converter,

ADC1

at rising edge of

TIM3

timer where I want to read the ADC value as soon as End of Conversion (

EOC

) of

ADC1

generates an interrupt. Below is the code. The interrupt handler,

ADC1_IRQHandler()

, however, is never called. Does anybody know what is wrong with the code?

&sharpinclude ''stm32f0xx.h''

&sharpinclude ''stm32f0xx_rcc.h''

&sharpinclude ''stm32f0xx_gpio.h''

&sharpinclude ''stm32f0xx_adc.h''

&sharpinclude ''stm32f0xx_tim.h''

&sharpinclude ''stm32f0xx_misc.h''

int g_adc_value;

void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

{

  GPIOx->ODR ^= GPIO_Pin;

}

void RCC_Config()

{

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);    

}

void GPIO_Config()

{

    GPIO_InitTypeDef GPIO_InitStruct;

    /* PinA0 as Analog input */

    GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_0;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AN;

    GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* PinA4 as digital output to drive LED */

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;

    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; // LED has an on-board resistor

    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void ADC_Config()

{

    NVIC_InitTypeDef NVIC_InitStructure;

    // Enable the TIM3 global Interrupt

    NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    // ADC1 IT Enable

    ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);

    ADC_InitTypeDef  ADC_InitStructure;

    ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;

    ADC_Init(ADC1, &ADC_InitStructure); // Do setup!

    ADC_ChannelConfig(ADC1,ADC_Channel_0,ADC_SampleTime_1_5Cycles);

    ADC_GetCalibrationFactor(ADC1);

    ADC_Cmd(ADC1, ENABLE); // Enable ADC1

    while (ADC_GetFlagStatus (ADC1, ADC_FLAG_ADEN) == RESET);

    while (ADC_GetFlagStatus (ADC1, ADC_FLAG_ADRDY) == RESET);

}

void TIM3_Config() // Timing of ADC1

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    /* Time base configuration */

    TIM_TimeBaseStructure.TIM_Period = (48000000 / 40000) - 1; // 40 KHz

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    /* TRGO selection */

    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T3_TRGO

    /* enable counter */

    TIM_Cmd(TIM3, ENABLE);

}

void ADC1_IRQHandler(void)

{

    if(ADC_GetITStatus(ADC1,ADC_IT_EOC))

    {

        GPIO_ToggleBits(GPIOA, GPIO_Pin_4);

        g_adc_value = ADC_GetConversionValue(ADC1);

        ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);

    }

}

int main(void) {

    SystemInit();

    GPIO_Config();

    TIM3_Config();

    ADC_Config();

    ADC_StartOfConversion(ADC1); // Start conversion

    GPIO_SetBits(GPIOA, GPIO_Pin_4); // LED off

    while (1) {

    }

}

#stm32f030-adc-interrupt
3 REPLIES 3
Posted on July 17, 2016 at 23:24

You need to actually call RCC_Config(), as one of the first things. I would also only enable the IRQ in the ADC after you have the ADC configuration finished.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mojtahedzadeh
Associate II
Posted on July 17, 2016 at 23:43

Hi Clive,

Thanks for your hints! I modified the code according to your hints, but there is still no call to the

ADC1_IRQHandler()

function!

Here is the modified code:

#include ''stm32f0xx.h''

#include ''stm32f0xx_rcc.h''

#include ''stm32f0xx_gpio.h''

#include ''stm32f0xx_adc.h''

#include ''stm32f0xx_tim.h''

#include ''stm32f0xx_misc.h''

int g_adc_value;

void RCC_Config()

{

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);

}

void GPIO_Config()

{

    GPIO_InitTypeDef GPIO_InitStruct;

    /* PinA0 as Analog input */

    GPIO_InitStruct.GPIO_Pin =  GPIO_Pin_0;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AN;

    GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* PinA4 as digital output to drive LED */

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_3;

    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; // LED has an on-board resistor

    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void ADC_Config()

{

    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    ADC_InitTypeDef  ADC_InitStructure;

    ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;

    ADC_Init(ADC1, &ADC_InitStructure); // Do setup!

    ADC_ChannelConfig(ADC1,ADC_Channel_0,ADC_SampleTime_1_5Cycles);

    ADC_GetCalibrationFactor(ADC1);

    ADC_Cmd(ADC1, ENABLE); // Enable ADC1

    while (ADC_GetFlagStatus (ADC1, ADC_FLAG_ADEN) == RESET);

    while (ADC_GetFlagStatus (ADC1, ADC_FLAG_ADRDY) == RESET);

    // ADC1 IT Enable

 

    ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);

 

}

void TIM3_Config() // Timing of ADC1

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    /* Time base configuration */

    TIM_TimeBaseStructure.TIM_Period = (48000000 / 40000) - 1; // 40 KHz

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    /* TRGO selection */

    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T3_TRGO

    /* enable counter */

    TIM_Cmd(TIM3, ENABLE);

}

void ADC1_IRQHandler(void)

{

    if(ADC_GetITStatus(ADC1,ADC_IT_EOC))

    {

        GPIO_SetBits(GPIOA, GPIO_Pin_4); // LED off

 

        g_adc_value = ADC_GetConversionValue(ADC1);

        ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);

    }

}

int main(void) {

    SystemInit();

    RCC_Config();

 

    GPIO_Config();

    TIM3_Config();

    ADC_Config();

    ADC_StartOfConversion(ADC1); // Start conversion

    GPIO_ResetBits(GPIOA, GPIO_Pin_4); // LED on

 

    while (1) {

    }

}

Edit 1: I realized that the following code makes Timer 3 not to generate Trigger (T3_TRGO)! Any idea?

    NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;

 

    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;

 

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 

    NVIC_Init(&NVIC_InitStructure);

 

mojtahedzadeh
Associate II
Posted on July 20, 2016 at 13:36

I found the problem!

It is because of a strange definition in

stm32f0xx.h

where for

STM32F030F4P6

chips (and for some non-sense reasons) we have to use the definition

ADC1_IRQn

instead of standard definition

ADC1_COMP_IRQn

. This makes the programmer to use the name

ADC1_IRQHandler()

for the interrupt service routine, but the compiler searches for the function

ADC1_COMP_IRQHandler()

. This makes the run of program problematic because the program counter will be lost when

EOC

interrupt is generated. Hope this saves hours of wasting time to find out a non-sense definition as the source of the problem.