STM32 外部中断和NVIC嵌套中断向量控制器
STM32 外部中断和NVIC嵌套中断向量控制器
STM32微控制器的中断系统是其核心功能之一,能够帮助开发者实现高效的任务调度和响应。本文将详细介绍STM32的外部中断和NVIC嵌套中断向量控制器的相关知识,包括EXTI的功能和特性、中断线的定义和作用、优先级分组,以及具体的配置步骤和程序实例。
背景
单片机开发过程中经常要用到外部中断(端口为双边沿触发、上升沿、下降沿触发)。在配置中断的过程中,又需要涉及到中断优先级的配置,中断优先级配置就要NVIC来设置。
外部中断/事件控制器(EXTI)
对于互联型产品,外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,对于其它产品,则有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。
主要特性
EXTI控制器的主要特性如下:
- 每个中断/事件都有独立的触发和屏蔽
- 每个中断线都有专用的状态位
- 支持多达20个软件的中断/事件请求
- 检测脉冲宽度低于APB2时钟宽度的外部信号。
功能说明
要产生中断,必须先配置好并使能中断线。根据需要的边沿检测设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。
如果需要产生事件,必须先配置好并使能事件线。根据需要的边沿检测通过设置2个触发寄存器,同时在事件屏蔽寄存器的相应位写’1’允许事件请求。当事件线上发生了需要的边沿时,将产生一个事件请求脉冲,对应的挂起位不被置’1’。
通过在软件中断/事件寄存器写’1’,也可以通过软件产生中断/事件请求。
外部中断线
事件与中断的区别
嵌套向量中断控制器
特性
- 68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线);
- 16个可编程的优先等级(使用了4位中断优先级);
中断线(Interrupt Line)
是指用于触发中断请求的信号线。在STM32微控制器中,中断线是连接外设和中断控制器的重要部分,用于检测外设事件的发生并触发中断请求。
中断线的定义和作用
中断线是STM32微控制器中用于检测外部或内部事件(如定时器溢出、按键输入、串口数据到达等)的信号线。当这些事件发生时,中断线会向中断控制器发送中断请求,中断控制器根据优先级管理机制决定是否响应该请求。如果响应,则会暂停当前执行的程序,转而执行相应的中断服务程序(ISR),处理完中断后再返回到原来的程序继续执行。
STM32中断线的分类和数量
STM32的中断线可以分为内核中断和外部中断。以STM32F103C8T6为例,它支持70个中断,其中包括10个内核中断和60个外部中断。外部中断涵盖了EXTI(外部中断/事件控制器)、TIM(定时器)、ADC(模拟数字转换器)、I2C、SPI等外设。
NVIC把外部的中断信号关联到内核中,将各种中断进行分门别类,按前后顺序发送给内核。嵌套中断向量控制器中的嵌套,表示中断也可以被其他更高优先级的中断事件中断。这就涉及到中断分组的概念。
优先级分组
抢占优先级(Preemption Priority)
用于决定当多个中断同时发生时,哪个中断的处理器会被首先服务。抢占优先级高的中断会抢占正在执行的低优先级中断。
子优先级(Sub-Priority)
在两个或多个中断具有相同抢占优先级时,子优先级决定了哪个中断被首先服务。如果两个中断具有相同的抢占优先级,则子优先级较低的中断会先被服务。
抢占优先级和子优先级的设置值越低优先级越高。如果中断优先级完全相同,同时触发的话,查看谁在中断列表前面可知谁先执行。
外部中断的配置
配置STM32的中断线通常包括以下几个步骤:
第一步、使能GPIO组和AFIO时钟的外设
需要通过设置AFIO寄存器来配置外部中断的输入模式。
第二步、配置外部中断线路
首先需要配置触发中断的外设,如GPIO、定时器、ADC等。
第三步、配置EXTI
设置外部中断的具体参数,如触发条件等。
第四步、配置NVIC
通过NVIC(Nested Vectored Interrupt Controller)设置中断的优先级和分组。
第五步、编写中断服务函数
根据不同的中断源编写相应的中断服务函数。例如,对于EXTI4的中断服务函数命名为EXTI4_IRQHandler,对于EXTI9_5的中断服务函数命名为EXTI9_5_IRQHandler。
通过以上步骤,可以有效地配置和使用STM32的中断线,实现高效的中断处理和系统响应。
程序实例
void NVIC_Configuration(void){ //嵌套中断向量控制器 的设置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
}
void PORTA6_EXITI_INIT (void){ //按键中断初始化
NVIC_InitTypeDef NVIC_InitStruct; //定义结构体变量
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //启动GPIO时钟 (需要与复用时钟一同启动)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);//配置端口中断需要启用复用时钟
//第1个中断
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource4); //定义 GPIO 中断
EXTI_InitStruct.EXTI_Line=EXTI_Line4; //定义中断线
EXTI_InitStruct.EXTI_LineCmd=ENABLE; //中断使能
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt; //中断模式为 中断
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //下降沿触发
EXTI_Init(& EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel=EXTI4_IRQn; //中断线
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能中断
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级 2
NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; //子优先级 2
NVIC_Init(& NVIC_InitStruct);
}
void EXTI4_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line4)!=RESET){//判断某个线上的中断是否发生
//---中断处理部分 ---
EXTI_ClearITPendingBit(EXTI_Line4); //清除 LINE 上的中断标志位
}
}
本文原文来自CSDN