STM32F4 NVIC or Nested Vector Interrupt Controller

Interrupts are important in microcontrollers. WIth them you are able to stop executing main program and jump to some predefined area if there is something important.

I already used interrupts in my USART library. There is an interrupt called each time data arrive to MCU.

Defferent peripheral can trigger interrupt, like data come to USART, ADC finished conversion, timer overflow, and more more.

NVIC

NVIC or Nested Vector Interrupt Controller is used to dinamically tell which interrupt is more important and for enabling or disabling interrupts. It supports up to 256 different interrupt vectors.

NVIC Structure

This is defined in “misc.h” file in CMSIS pack.

NVIC structure accept 4 parameters.

NVIC_IRQChannel

Here you tell for which interrupt you will set settings.

NVIC_IRQChannelPreemptionPriority

With this parameter you set interrupt priority, number from 0x00 to 0x0F. Let’s say we have to use USART receive interrupt and ADC conversion finished interrupt. USART is more important than ADC, so USART will have lower number than ADC.

NVIC_IRQChannelSubPriority

With this parameter you set interrupt priority, number from 0x00 to 0x0F. Let’s say you have 2 USARTs enabled, but USART1 is more important than USART2. So USART1 will have lower number than USART2.

NVIC_IRQChannelCmd

With that you select if interrupt is enabled or disabled.

Example

Handle interrupts

For handling interrupts we can use special defined function names. In our example, for handle USART1 interrupts, we can use something like this

 

tilz0R

Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • Mohamed El Shenawy

    Hi , I have a problem in the program after enabling the ADC interrupt , The processor doesn’t do anything after starting ADC_READ
    Here is a simple program which reads data from ADC in continuous mode and when the conversion ends it calls the ADC interrupt handler to send these data to USART and be displayed on the terminal and All of this works fine and the data are displayed continuously.

    When I tried to add lines of code after the function TM_ADC_Read ,These lines are not executed (for example in this example I am setting pin A6 and Pin A4 , but they are not set!)

    void EnableADCInterrupts(void )

    {

    NVIC_InitTypeDef nvicStructure;

    nvicStructure.NVIC_IRQChannel = ADC_IRQn ;

    nvicStructure.NVIC_IRQChannelPreemptionPriority = 2;

    nvicStructure.NVIC_IRQChannelSubPriority = 2;
    /*There are no other interrupts enabled in my code , However I gave those the value 2 and I tried to give them all value to 15 and the problem exists*/
    nvicStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&nvicStructure);

    }

    int main(void) {

    /* Initialize system */

    SystemInit();

    /* Initialize Delay library */

    TM_DELAY_Init();

    /* Initialize USART1, 115200baud, TX: PB6 */

    TM_USART_Init(USART1, TM_USART_PinsPack_2, 115200);

    /* Initialize ADC1 on channel 0, this is pin PA0 */

    InitializeGP();

    EnableADCInterrupts(); /*After calling this function problems happened, see downwards*/

    /* Initialize ADC1 on channel 3, this is pin PA3 */

    TM_ADC_Init(ADC1, ADC_Channel_5);

    TM_USART_Puts(USART1 , “USART IS OKAY n r”);

    /* Read ADC1 Channel0 Read ADC1 Channel3 */

    sprintf(str, “%4d: nr”, TM_ADC_Read(ADC1, ADC_Channel_5));

    /* Put to USART */

    TM_USART_Puts(USART1, str);

    /**These two functions don’t execute after I called EnableAdcInterrupts**/

    GPIO_WriteBit(GPIOD , GPIO_Pin_5 , Bit_SET);

    GPIO_WriteBit(GPIOD , GPIO_Pin_4 , Bit_SET);

    /* Little delay */

    Delayms(100);

    while (1);

    }

    void ADC_IRQHandler (void)

    {

    if (ADC_GetITStatus( ADC1,ADC_IT_EOC) != RESET)

    {

    /* Clear the End of conversion flag*/

    /* Send reading to USART6*/

    sprintf(str, “%4d: nr”, TM_ADC_Read(ADC1, ADC_Channel_5));

    /* Put to USART */

    TM_USART_Puts(USART1, str);

    }

    ADC_ClearITPendingBit( ADC1, ADC_IT_EOC);

    }

    The PA6 and PA4 pins are not set , however when I disable the interrupt through the function EnableAdcInterrupt , they work fine .

    would you tell me what’s the problem?

    • For sure, I can tell you that you are missing call function ADC_ITConfig and set which IT will be in use.

      Probably something like:
      ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

      • Mohamed El Shenawy

        Hi Thank you for reply and for your awesome blog

        Actually I had the ADC_ITConfig function called in TM_ADC_InitADC() in tm_stm32f4_adc.c

        But the problem actually was that usart was taking much cpu cycles , that results in an overflow so cycling endless in the ADC interrupt.

        as fm stated here :
        http://goo.gl/sIWy7z
        when I deleted the USART part and increased the two sampling delay to 20 cycles .
        The code worked fine.

        Hopefully This is useful to someone else.

  • HaMiD Sani

    Hi,

    I’m trying to control a BLDC and need to send PWM to a motor driver chip. Now I had to make a few modifications to the PWM libraries that you provided so I decided to just go ahead and initialize everything myself. Now the problem that I have is that when I turn on the timer interrupt it never gets handled. I use LED’s and Oscilloscope to debug and the code never runs the timer handler and gets stuck somewhere. If I uncomment the interrupt initialization (TIM_ITConfig) then the rest of the code works fine, without the timer interrupt of course. I’ve checked everything several times and tested time 2, 3 , and 4 with no success for the past few days. A look from a fresh set of eyes can be very helpful. I just can’t see what I’m missing. Thanks

    int main(void) {

    /* Initialize system */
    SystemInit();

    /*************** LED INITIALIZATION ****************/
    /* Initialize leds on board */
    TM_DISCO_LedInit();

    /* Turn on Orange leds to show progress*/
    TM_DISCO_LedOn(LED_BLUE);

    /*************** Timer INITIALIZATION **************/
    /* Initialize TIM3 & OC, PinsPack 1, Ch 1 (PA6), 2 (PA7), 3 (PB0) */
    Timer3_Config();

    while(1){

    }
    }

    • From this here, I really can’t know what is your problem
      Do you have timer handler function declared?

  • Roby Ardiansyah

    is this compatible with your library?

    • With which my lib?

      • Roby Ardiansyah

        usb vcp/otg hs/fs as usart?

        • I don’t understand you nothing.
          Please ask clear question! With description!

          • Roby Ardiansyah

            im sorry for my bad english,
            is your vcp library (library 24) has “handling interrupt” like this?

          • Yes, it does.

          • Roby Ardiansyah

            oke thank you, i just dont understand how it works
            maybe, i have to read your vcp library again.
            🙂

  • Gokul Sriram P

    I’m programming STM32 from scratch without CMSIS library. I have problem enabling interrupts. Please help.

    • Where did you stuck in programming?
      BTW: Why no CMSIS library? At least Cortex-M CMSIS should be used.

  • utsav desai

    hello,TIM2_IRQn in this interrupt handler n represent for what?

    • For all TIM2 events and interrupts :))

      • utsav desai

        Thank you, is there any chance for using stm32f4xx in simulator?

        • Never tried, but Im sure there is a way for that.

  • Pingback: Embed with Elliot: Interrupts, The Good… | Hackaday()

  • Pingback: Embed with Elliot: Interrupts, The Good… | Hack The Planet()

  • Pingback: Embed with Elliot: Interrupts, The Good… | Ad Pub()

  • Pradeep Chl

    Do you what value should I pass at NVIC_InitStruct.NVIC_IRQChannel for nRF24L01+ device data reception or transmission ?

  • Murtaz Naqvi

    Can i write interrupt routines in main file?? or i have to write it in stm32f4xx_it.c

    • You can in main also.

      • Murtaz Naqvi

        One more question I was using keil pack 1.0.8 but when i flash it to STM32 discovery board it basically did nothing. Then i used your default project and copied my code and used keil pack 2.5 its start working. Can you plz explain me why this is happening.

        • I don’t know what you mean by “did nothing”.

          • Murtaz Naqvi

            means code was not working but after using your template the same code started working. And regarding previous question should i remove stm32f4xx_it.c file??

          • No, you should not remove this file. But I suggest you to use one file for all interrupts. It makes your code easier to maintain when using a lot of interrupt sources.

            I don’t know what could be wrong. Maybe startup process was wrong.

          • Murtaz Naqvi

            ok thankx

  • alin

    hello!
    does anybody know where is generated the interrupt handler for tim2 when you configure the timer and interrupt from cube?

    • Nowhere. You have to write it yourself and call HAL function.