STM32 Interrupt System
The STM32 has a very powerful interrupt system that divides interrupts into two types: kernel exceptions and external interrupts. and arrange all interrupts through a table, here is some of the stm32 interrupt vector table:
3 to 6 The area is marked black, and this area is the kernel exception. Kernel exceptions cannot be interrupted and cannot be prioritized (that is, priority is above the external interrupt). Common kernel exceptions are the following: Reset (reset), unshielded interrupt (NMI), hard error (Hardfault), and others can also be found on the table.
Starting with the 7th, all subsequent interrupts are external interrupts. External interrupts are what we must learn to master, including line interrupts, timer interrupts, IIC,SPI and other peripheral interrupts, configurable priority. There are two types of priority for external interrupts: preemption priority and response priority.
What is preemption priority?
Preemption priority comparison of high-handed, a word and cut the queue. Preemption is high enough to interrupt a low-priority task, and then return to the previous task after the higher-priority tasks have been executed. So when there are multiple tasks with different preemption priorities, there is a good chance that the nesting of tasks will occur.
What is the response priority level?
The response priority is slightly more modest and more polite. The response priority is also called the secondary priority, and if the preemption priority of the two tasks is the same, then the task with the higher priority will be executed first and not be interrupted by the next task with higher priority, so I say it is more polite.
Interrupt Controller (NVIC)
Because the Stm32 interrupt system is more complex, there is a controller in the kernel that specifically manages the interrupt:NVIC.
Nvic is responsible for the control of all interrupts except the Systick, which is very important!
In the standard library, we provide a set of APIs to control interrupts through NVIC, first we look at the Nvic_init () function, which first defines and populates a struct: nvic_inittypedef the struct is defined as follows:
Nvic_irqchannel the interrupt vectors that need to be configured
Nvic_irqchannelcmd interrupt response to enable or disable the corresponding interrupt vector
Nvic_irqchannelpreemptionpriority configuring preemption priority for corresponding interrupt vectors
Nvic_irqchannelsubpriority Configuring the response priority for the corresponding interrupt
The four members of the structure are better understood, and there is no longer any more to be said.
Note, however, that Nvic can only configure the priority of 16 interrupt vectors, and its preemption priority and response priority are determined by a 4-bit number. In the library function, it is divided into 5 different allocation methods:
Group No. 0: All 4 bits have a response priority and can configure 16 different response priorities. The interrupt priority is the same.
Group 1th: The highest one is used to configure preemption priority, and the remaining three bits are used to indicate the priority of the response. Then there are two different preemption priorities (0 and 1) and 8 different response priorities (0~7).
Group 2nd: High Two bits are used to configure preemption priority, and low levels are used to configure response priority. Then there are 4 kinds of priorities.
Group 3rd: High three bits are used to configure preemption priority, and low levels are used to configure response priority. There are 8 preemption priorities and 2 corresponding priority levels.
Group 4th: All bits are used to configure preemption priority, that is, there are 16 preemption priorities and no response attributes.
These 5 different allocation methods are configured according to the actual needs of the project.
The following APIs are configured:
NVIC_PriorityGroupConfig();
One of the following parameters can be entered in parentheses, representing the different allocation methods:
Nvic_prioritygroup_0
Nvic_prioritygroup_1
Nvic_prioritygroup_2
Nvic_prioritygroup_3
Nvic_prioritygroup_4
Exti External Interrupt
All Gpio STM32 are introduced to the Exti external interrupt line, which means that all IO ports are configured to trigger interrupts. Is the way to connect Gpio and Exti:
As we can see, there are a total of 16 interrupt lines: EXTI0 to EXTI15.
Each interrupt line corresponds to a total of 7 GPIO from Pax to PGX. That is, at the same time each of the disconnection can only be corresponding to a GPIO port interrupt, not the corresponding all the port interrupt event, but can be time-sharing, in the program execution process, this does not need us to care too much. The most we care about is the way the interrupt is triggered :
In Exti, there are three ways to trigger interrupts: rising edge trigger, falling edge trigger, and bilateral edge triggering. Depending on the circuit, we choose different triggering methods to ensure that interrupts can be triggered normally.
Instance
For the sake of understanding, here we will interrupt the configuration code to be pasted up.
void NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; /* 配置NVIC为优先级组1 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 配置中断源:按键1 */ NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //配置为EXTI0通道 /* 配置抢占优先级 */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 配置子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断通道 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //将上述配置参数传入中断初始化函数}
In addition to the configuration of the interrupt line, we also configure the corresponding PIN
void Exti_key_config (void) {gpio_inittypedef gpio_initstructure; Exti_inittypedef exti_initstructure; /* Turn on the key gpio port clock */Rcc_apb2periphclockcmd (rcc_apb2periph_gpioa| rcc_apb2periph_afio,enable); /* Configure NVIC Interrupt */nvic_configuration ();/*--------------------------KEY1 configuration-----------------------------*/* Select the GPI used for the key O */gpio_initstructure.gpio_pin = GPIO_PIN_0; /* configured as FLOATING NULL input */gpio_initstructure.gpio_mode = gpio_mode_in_floating; Gpio_init (Key1_int_gpio_port, &gpio_initstructure); /* Select Exti's signal source */Gpio_extilineconfig (GPIO_PORTSOURCEGPIOA, GPIO_PINSOURCE0); Exti_initstructure.exti_line = EXTI_LINE0; /* Exti for Interrupt mode */Exti_initstructure.exti_mode = Exti_mode_interrupt; /* Rising edge interrupt */Exti_initstructure.exti_trigger = exti_trigger_rising; /* Enable Interrupt */exti_initstructure.exti_linecmd = enable; Exti_init (&exti_initstructure);}
At this point, the interrupt configuration is complete. Believe you have seen that the above code is to configure PA0 as a rising edge interrupt. However, it is now only possible to say that the interrupt has been configured, but we are not able to use it yet. We also lack an execution function for interrupts.
When the interrupt is triggered, the program immediately jumps to the interrupt function to perform the interrupt operation, which is not done by default when the project is created. You need to add it yourself. It is also important to note that the name of the interrupt function must be provided by the standard library, otherwise it will not be recognized.
We open Startup_stm32f10x_hd.s This file, in which we can find such a code:
; 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 ... ... ...
It is not difficult to see thatExti0_irqhandler is the interrupt function of the interrupt line 0, so we add this function to the project. It is best to add to stm32f10x_it.c This file for easy administration.
You can add the function you want in this function, the code is as follows:
void EXTI0_IRQHandler(void){ //确保是否产生了EXTI Line中断 if(EXTI_GetITStatus(EXTI_Line0) != RESET) { /******/ //LED闪烁相关代码 /******/ //清除中断标志位 EXTI_ClearITPendingBit(EXTI_Line0); } }
At this point, the entire interruption of the flow of carding complete, if there is any mistake, welcome to discuss!