Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Interrupt is one of the most important functions in the MCU, through interrupt can improve the operation efficiency of the program, can be the MCU timely response to various peripheral requests. The interrupt of STM32 series MCU is mainly managed by nested vector interrupt controller.

The nested vector interrupt controller has the following characteristics:

  • 68 masked interrupt channels (excluding the 16 Cortex™-M3 interrupts);
  • 16 programmable priority levels (using 4-bit interrupt priority);
  • Low latency exception and interrupt handling;
  • Power management control;
  • The realization of system control register;

The nested vector interrupt Controller (NVIC) is closely linked to the processor core, enabling low latency interrupt processing and efficient processing of late interrupts.

The external interrupt/event controller consists of 19 edge detectors that generate event/interrupt requests. Each input line can be independently configured with the input type (pulse or suspend) and corresponding triggering events (rising or falling or both). Each input line can be screened independently. The suspend register holds the interrupt request for the state line.

The main characteristics of EXTI controller are as follows:

  • Each interrupt/event has its own triggering and masking
  • Each interrupt line has a dedicated status bit
  • Supports interrupt/event requests for up to 20 software
  • Detects external signals whose pulse width is lower than the APB2 clock width. Refer to the electrical characteristics section of the data sheet for related parameters.

Interrupt control block diagram is as follows:

The following key port as an interrupt detection port, to demonstrate the use of interrupt.

//KEY0 PC1 KEY1 PC13 WK_UP PA0

void KEY_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		// Pull up input
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;		// Drop input
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}
Copy the code

The IO port used by the key is initialized first. Three keys are used here. One of the keys is low by default, and becomes high after the key is pressed. The remaining two keys are high by default and low when pressed. Let’s start the initialization interrupt.

//KEY0 PC1 KEY1 PC13 WK_UP PA0
void EXTIx_Init(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 1. Initialize the IO
    KEY_Init();													// Key port initialization
    // 2. Start AFIO clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 		// Enable the function clock reuse function
    // 3. Set the mapping between the I/O port and the interrupt line
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);	//PA0
    // 4. Set trigger condition for initialization line interruption
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;					/ / WK_UP rise along
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);	//PC1

    EXTI_InitStructure.EXTI_Line = EXTI_Line1;					/ / KEY0 drop down
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);//PC13

    EXTI_InitStructure.EXTI_Line = EXTI_Line13;					/ / KEY1 rise along
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    // 5. Configure interrupt group and enable interrupt
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) ! = RESET) { delay_ms(10);
        if(WK_UP == 1) { LED0 = ! LED0; LED1 = ! LED1; } EXTI_ClearITPendingBit(EXTI_Line0); }}void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line1) ! = RESET) { delay_ms(10);
        if(KEY0 == 1)
        {
            LED0 = !LED0;
        }
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}
void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line13) ! = RESET) { delay_ms(10);
        if(KEY1 == 1)
        {
            LED1 = !LED1;
        }
        EXTI_ClearITPendingBit(EXTI_Line13);
    }

}
Copy the code

During initialization, you need to set the interrupt line corresponding to each I/O interface. The connection between the interrupt line is shown as follows:

It can be seen from the figure above that all ports P0 correspond to median line 0, all ports P1 correspond to median line 1, and so on. The three keys used here are PC1, PC13 and PA0, that is, the corresponding interrupt line is interrupt line 1, interrupt line 13 and interrupt line 0.

After the interrupt line is set, the interrupt group needs to be set, that is, the interrupt priority needs to be set. When the interrupt is triggered at the same time, the interrupt with higher priority will be processed first.

After the interrupt line is set, the interrupt entry function needs to be provided, because when the interrupt is triggered, the system will automatically jump to the interrupt entry function and execute the interrupt function code. The function name for each interrupt entry is fixed and cannot be defined by itself. The entry name of the interrupt function can be viewed in the startup_stm32f10x_hs.s file.

                ; External Interrupts
                DCD     WWDG_IRQHandler            ; Window Watchdog
                DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
                DCD     TAMPER_IRQHandler          ; Tamper
                DCD     RTC_IRQHandler             ; RTC
                DCD     FLASH_IRQHandler           ; Flash
                DCD     RCC_IRQHandler             ; RCC
                DCD     EXTI0_IRQHandler           ; EXTI Line 0
                DCD     EXTI1_IRQHandler           ; EXTI Line 1
                DCD     EXTI2_IRQHandler           ; EXTI Line 2
                DCD     EXTI3_IRQHandler           ; EXTI Line 3
                DCD     EXTI4_IRQHandler           ; EXTI Line 4
                DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2
                DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9.. 5
                DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
                DCD     TIM1_UP_IRQHandler         ; TIM1 Update
                DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
                DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
                DCD     TIM2_IRQHandler            ; TIM2
                DCD     TIM3_IRQHandler            ; TIM3
                DCD     TIM4_IRQHandler            ; TIM4
                DCD     I2C1_EV_IRQHandler         ; I2C1 Event
                DCD     I2C1_ER_IRQHandler         ; I2C1 Error
                DCD     I2C2_EV_IRQHandler         ; I2C2 Event
                DCD     I2C2_ER_IRQHandler         ; I2C2 Error
                DCD     SPI1_IRQHandler            ; SPI1
                DCD     SPI2_IRQHandler            ; SPI2
                DCD     USART1_IRQHandler          ; USART1
                DCD     USART2_IRQHandler          ; USART2
                DCD     USART3_IRQHandler          ; USART3
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15.10.
                DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
                DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
                DCD     TIM8_UP_IRQHandler         ; TIM8 Update
                DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
                DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare
                DCD     ADC3_IRQHandler            ; ADC3
                DCD     FSMC_IRQHandler            ; FSMC
                DCD     SDIO_IRQHandler            ; SDIO
                DCD     TIM5_IRQHandler            ; TIM5
                DCD     SPI3_IRQHandler            ; SPI3
                DCD     UART4_IRQHandler           ; UART4
                DCD     UART5_IRQHandler           ; UART5
                DCD     TIM6_IRQHandler            ; TIM6
                DCD     TIM7_IRQHandler            ; TIM7
                DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1
                DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2
                DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3
                DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
Copy the code

The interrupt vector table here lists all interrupt function entry names.

When the key is pressed, the program will jump to the interrupt function, in the interrupt function through the LED light to indicate the effect of different keys pressed.