68个可屏蔽中断通道,包括EXTI,TIM,ADC,USART,SPI,I²C,RTC等多个外设(F1系列最多的数量,以型号为主);
使用NVIC统一管理中断,每个中断通道都拥有16个可编程优先等级,可以对优先级进行分组,进一步设置抢占优先级和响应优先级。
AFIO内部图
EXTI内部图
中断和事件的区别
NVIC的中断优先级由优先级寄存器的4位(0-15)决定,这四位可以进行切分,分为高N位的抢占优先级,
和4-n位的响应优先级;
抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的话,
按照中断号排队。
操作的是NVIC->IPRx寄存器
中断示例
main
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OUT1.H"
#include "Interrupt.h"
int main(void)
{
OUT1_Init();
Interrupt_Init();
OUT1_OFF();
while(1)
{
Delay_s(5);
OUT1_OFF();
}
}
interrupt.c
#include "stm32f10x.h" // Device header
#include "OUT1.h"
void Interrupt_Init (void)
{
//开启GPIOC的时钟控制
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
//开启AFIO的时钟控制
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//EXTI的时钟控制不需要开启
//NVIC也不需要开启,NVIC是属于内核内的外设
/*配置GPIO */
GPIO_InitTypeDef GPIO_InitStructur;
GPIO_InitStructur.GPIO_Mode=GPIO_Mode_IPU; //设置成上拉输入
GPIO_InitStructur.GPIO_Pin=GPIO_Pin_15; //选择15号Pin脚
GPIO_InitStructur.GPIO_Speed=GPIO_Speed_50MHz; //不重要
GPIO_Init(GPIOC,&GPIO_InitStructur); //选择C组的GPIO
/*配置AIFO */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource15); //设置PC15为外部中断线
/*配置EXIT */
EXTI_InitTypeDef EXTI_Initstructure;
EXTI_Initstructure.EXTI_Line=EXTI_Line15; //配置中断线
EXTI_Initstructure.EXTI_LineCmd=ENABLE; //是否开启中断
EXTI_Initstructure.EXTI_Mode=EXTI_Mode_Interrupt; //配置成中断
EXTI_Initstructure.EXTI_Trigger=EXTI_Trigger_Rising; //配置成上升沿触发
EXTI_Init(&EXTI_Initstructure);
/*配置NVIC 配置中断分组 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断抢占优先级和响应优先级分组
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; //配置抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; //配置响应优先级
NVIC_Init(&NVIC_InitStruct);
}
/*编写中断函数,中断函数的名字都是固定的,中断函数都是无参数无返回值的 */
/*编中断函数的函数名可以在启动文件startup_stm32f10x_md.s中可以找到 */
/*中断函数的名字都是以_IRQHandler结尾 */
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line15)==SET)
{
/*编写中断程序 */
OUT1_ON();
EXTI_ClearITPendingBit(EXTI_Line15); //清除中断标志位
}
}
interrupt.h
#ifndef __Interrupt_H
#define __Interrupt_H
void Interrupt_Init (void);
#endif