中断:在主程序运行过程中,出现了特定事件(例如发生已经预知的一些情况),从而转入中断程序中,处理完成后再回到主程序中继续执行。(频繁的中断函数会影响主程序的运行,所以中断函数一边不处理特别复杂的逻辑)
EXTI(Extern Interrupt)外部中断
支持的触发方式:上升沿/下降沿/双边沿/软件触发
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒(0-15:对应GPIO_PIN 0-15中断;16:PVD输出;17:RTC闹钟事件;18:USB唤醒事件;19:连接到以太网唤醒事件(只适用于互联型产品))
触发响应方式:中断响应/事件响应
注意EXTI9_5和EXTI15_10这几个中断在两个通道里,需要通过标志位判断。
EXTI中断发生流程:EXTI监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
NVIC(Nested vectoredinterrupt controller)嵌套向量中断控制器
NVIC提供了灵活、高效、可扩展的中断处理机制,支持多级优先级、多向中断、嵌套向量中断等特性。
NVIC支持多级优先级,可以配置不同的优先级和互斥优先级组。中断控制器负责中断的挂起、解挂和优先级管理。
通过检测GPIO的PB14的电平变化触发中断的实例:
初始化:
void EXTI_NVIC_Init(void){/* GPIO --> AFIO */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOB口时钟,因为检测的是PB14口的电平信号RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO时钟GPIO_InitTypeDef GPIO_InitStructure; //初始化PB14引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);/* AFIO --> EXTI */EXTI_InitTypeDef EXTI_InitStructure; //初始化EXTIEXTI_InitStructure.EXTI_Line =EXTI_Line14; //选择14号线EXTI_InitStructure.EXTI_LineCmd =ENABLE; //14号线使能EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt; //选择模式,这里是中断模式触发中断,如果是EXTI_Mode_Event,就是触发一个事件EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Falling; //触发方式:EXTI_Trigger_Falling ,EXTI_Trigger_Rising_Falling ,EXTI_Trigger_Rising,这里选的是下降沿触发EXTI_Init(&EXTI_InitStructure);/* EXTI --> NVIC */ //开启NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置优先分组为2,这里是随便设置的 NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = 40; //EXTI15_10_IRQn=40, /*!< External Line[15:10] Interrupts */ 选择配置EXTI15_10线这里PB14在EXTI15_10中NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //线路使能NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //响应优先级NVIC_Init(&NVIC_InitStruct); //初始化 }
中断函数:
void EXTI15_10_IRQHandler(void){ //函数名为预留的指定名称,可以从启动文件复制//中断标志位判断if(EXTI_GetITStatus(EXTI_Line14) == SET){ //判断是否是14号线触发的中断/*可添加一些操作*count++;*/EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志 } }