1. Basic concepts
The armcoetex-m3 kernel supports 256 interrupts, including 16 internal interrupts, 240 external interrupts and 256-level programmable interrupt priority Settings.STM32 currently supports a total of 84 interrupts (16 internals +68 externals), as well as 16 levels of programmable interrupt priority Settings, using only the 4 bit higher of the 8bit interrupt priority Settings.
STM32 can support 68 interrupt channels, which have been fixed to the corresponding external devices. Each interrupt channel has its own interrupt priority control byte PRI_n(8 bits, but STM32 only USES 4 bits, high 4 bits is effective). The 8-bit interrupt priority control word of each 4 channels constitutes a 32-bit priority register.The 68 channel priority control words constitute at least 17 32-bit priority registers.
The 4bit interrupt priority can be divided into two groups. From the high order, the preemptive priority is defined before, and the response priority is defined after.According to this grouping, 4 bits can be divided into 5 groups
Group 0: all 4bits are used to specify response priority;
Group 1: the highest bit is used to specify preemptive priority, and the next three bits are used to specify response priority;
Group 2: the highest two bits are used to specify preemptive priority, and the next two bits are used to specify response priority;
Group 3: the highest 3 bits are used to specify preemptive priority, and the following 1 bit is used to specify response priority;
Group 4: all four bits are used to specify preemptive priority.
The relationship between preemptive priority and response priority is that interrupts with high preemptive priority can be responded to in interrupt processing with low preemptive priority, namely interrupt nesting.
When the preemptive priorities of two interrupt sources are the same, there is no nesting relationship between the two interrupts. If another interrupt is being processed after the arrival of one interrupt, the incoming interrupt will not be processed until the processing of the previous interrupt is completed.If both interrupts arrive at the same time, the interrupt controller decides which one to process first according to their response priority.If they have equal preemptive and response priorities, they decide which one to process first based on their precedence in the interrupt table.Each interrupt source must have two priorities defined.
A few things to note:
1) if the specified preemptive priority or response priority exceeds the scope of the selected priority group, unexpected results may be obtained;
2) there is no nesting relationship between interrupt sources with the same preemptive priority;
3) if an interrupt source is specified as a preemptive priority level, and no other interrupt source is in the same preemptive priority level, then any valid response priority level can be specified for this interrupt source.
2. GPIO external interrupt
In STM32, each GPIO can trigger an external interrupt, but GPIO interrupts are grouped in one unit, and external interrupts between groups can only be used one at a time.For example, PA0, PB0, PC0, PD0, PE0, PF0, and PG0 are groups of 1. If we use PA0 as an external interrupt source, the others cannot be used anymore. In this case, we intelligently use external interrupt sources with different terminal Numbers like PB1 and PC2.Each group USES an interrupt flag, EXTIx.The five external interrupts, EXTI0 -- EXTI4, have their own separate interrupt response function. Exti5-9 shares one interrupt response function and exti10-15 shares one interrupt response function.
For interrupt control, STM32 has a dedicated governing body: NVIC.For a detailed explanation of NVIC, please refer to the authoritative guide to ARM cortex-m3, written by Joseph Yiu, translated by song yan, published by beihang university press, chapter 8 NVIC and interrupt control.The enable, suspend, priority, activity, and so on are managed by NVIC.
3. Program development
In fact, the above basic concepts and knowledge of STM32 interrupt system is only a general understanding, with the program will be able to speak more to deepen the use of interrupt.The basic steps for using external interrupts are as follows:
1. Set the appropriate clock;
2. Set the corresponding interrupt;
IO port initialization; 3.
4. Set the corresponding IO port as interrupt line (before setting external interrupt) and initialize it;
5. Interrupt function in the response function of the selected interrupt channel.
Experiment process: press the button to trigger the corresponding interrupt.According to the schematic diagram, K2/K1/K0 connects PE2/PE3/PE4, so I will use EXTI2/EXTI1/EXTI0 for three external interrupts.PB5/PE5 are connected with two LED lights respectively.The effect of the interrupt is to press the button and the corresponding LED light will be activated.
Set the appropriate clock
First you need to open GPIOB, GPIOE (because the other end of the key is connected to the PE port).Then, since it is to be used to trigger interrupts, you also need to turn on the GPIO multiplexing clock.The detailed code is as follows:
Void RCC_cfg ()
{
// open PE PB port clock and open multiplexing clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
}
The RCC function required to set the appropriate clock is in stm32f10x_rcc.c, so add this file to your project.
Set up the appropriate interrupt
Setting the corresponding interrupt is actually setting NVIC. In STM32's firmware library, there is a structure NVIC_InitTypeDef, which has the corresponding flag bit setting, and then NVIC_Init() function is used for initialization.The detailed code is as follows:
Void NVIC_cfg ()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);// select interrupt grouping 2
NVIC_InitStructure. NVIC_IRQChannel = EXTI2_IRQChannel;// select interrupt channel 2
NVIC_InitStructure. NVIC_IRQChannelPreemptionPriority = 0;// preemptive interrupt priority is set to 0
NVIC_InitStructure. NVIC_IRQChannelSubPriority = 0;// the response interrupt priority is set to 0
NVIC_InitStructure. NVIC_IRQChannelCmd = ENABLE;// enable interruption
NVIC_Init (& NVIC_InitStructure);
NVIC_InitStructure. NVIC_IRQChannel = EXTI1_IRQChannel;// select interrupt channel 1
NVIC_InitStructure. NVIC_IRQChannelPreemptionPriority = 1;// preemptive interrupt priority is set to 1
NVIC_InitStructure. NVIC_IRQChannelSubPriority = 1;// the response interrupt priority is set to 1
NVIC_InitStructure. NVIC_IRQChannelCmd = ENABLE;// enable interruption
NVIC_Init (& NVIC_InitStructure);
NVIC_InitStructure. NVIC_IRQChannel = EXTI0_IRQChannel;// select interrupt channel 0
NVIC_InitStructure. NVIC_IRQChannelPreemptionPriority = 2;// preemptive interrupt priority is set to 2
NVIC_InitStructure. NVIC_IRQChannelSubPriority = 2;// the response interrupt priority is set to 2
NVIC_InitStructure. NVIC_IRQChannelCmd = ENABLE;// enable interruption
NVIC_Init (& NVIC_InitStructure);
}
Because there are three interrupts, you need three bits to specify preemption priority as described earlier, so select group 2.
3.IO port initialization
Void IO_cfg ()
{
GPIO_InitTypeDef GPIO_InitStructure;
/ / / / / / / / / / / LED / / / / / / / / / / / / / /
GPIO_InitStructure. GPIO_Pin = GPIO_Pin_5;// select pin 5
GPIO_InitStructure. GPIO_Mode = GPIO_Mode_PP;// select input mode push pull output
GPIO_InitStructure. GPIO_Speed = GPIO_Speed_50MHz;// the maximum output frequency is 50MHz
GPIO_Init (GPIOE, & GPIO_InitStructure);/ / set PE5
GPIO_InitStructure. GPIO_Pin = GPIO_Pin_5;// select pin 5
GPIO_Init (GPIOB, & GPIO_InitStructure);/ / set PB5
/ / / / / / / / / KEY / / / / / / / / / / / / / / / / / / / / / / / / /
GPIO_InitStructure. GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;// select pin 2,3,4
GPIO_InitStructure. GPIO_Speed = GPIO_Speed_50MHz;// the maximum output frequency is 50MHz
GPIO_InitStructure. GPIO_Mode = GPIO_Mode_Out_PP;// output with pull resistance
GPIO_Init (GPIOE, & GPIO_InitStructure);
GPIO_ResetBits (GPIOE, GPIO_P