1、STM 32的中断系统
1、中断、中断源、中断向量、中断优先级、中断服务函数......
2、ARM Cortex M3内核支持256个中断,包括16个内核中断和240个外设中断,拥有256个中断优先级别。
3、STM 32的中断通道可能会由多个中断源共用。这就意味着,某一个中断服务函数也可能被多个中断源所共用。所以,在中断服务函数的入口处,需要有一个判断机制,用以辨别是那个中断触发了中断。
4、入口处,需要有一个判断机制,用以辨别是那个中断触发了中断。
5、STM32中有2个优先级的概念:抢占优先级和响应优先级,每个中断都需要指定这两种优先级。
6、STM32微处理器的内核中有一个NVIC(嵌套向量中断控制器)的设备,它对中断进行统一的协调和控制,其中最主要的工作就是控制中断通道的使能和确定中断的优先级。
2、STM 32 外部中断
1、外部中断 EXTI是STM32微处理器实时处理外部事件的一种机制,由于中断请求主要来自GPIO端口的引脚,所以称为外部中断。
2、STM32芯片有16个外部中断源EXTI0~EXTI15,分别对应着7个中断向量,也就是对应着7个中断服务函数。
EXTI0、EXTI1、EXIT2、EXIT3、EXIT4:专用
EXTI5~EXTI9:共用 EXTI10~EXTI15:共用
3、EXTI0的连接引脚是:PA0~PGO,即每个端口组的0号引脚。以此类推。
4、外部中断的触发条件:上升沿触发、下降沿触发或双边沿触发。(不可以配置高电平触发或者低电平触发)
3、程序设计思路
3.1、传统的STM32外部中断设计步骤:
-
将GPIO初始化为输入端口
-
配置相关I/O引脚与中断线的映射关系
-
设置该I/O引脚对应的中断触发关系
-
配置NVIC(嵌套向量中断控制器),并使能中断
-
编写中断服务函数
3.2、基于STM32CubeMX的外部中断设计步骤:
【1】在STM32CubeMX中指定引脚,配置中断初始化参数。 选择GPIO引脚的功能,设置中断信号触发条件,使能NVIC对应的中断通道。 【2】重写该I/O引脚对应的中断回调函数。
4、举例:将PC13引脚设置成外部中断,下降沿触发,在中断服务函数中,翻转PB9的电平信号。
4.1、中断初始化配置
-
将GPIO设置为:GPIO_EXTI 功能。
-
设置中断触发条件:上升沿、下降沿、上升沿或下降沿
-
使能相关的NVIC通道。
4.2、中断服务函数的编写
5、实训案例:外部中断信号控制LED灯开关
【1】将KEY2,即PA5设置为外部中断输入,下降沿触发。在中断服务函数中,切换LED1的开关状态。
【2】将KEY4,即PB10设置为外部中断输入,上升沿触发。在中断服务函数中,切换LED2的开关状态。
利用STM32CubeMX配置中断程序中已经完成了中断程序的编写。
在主函数中查找中断函数:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init(); //中断程序在初始化GPIO中进行了编写(可跳转定义进行查看)
}
/*转到定义后可以看到:*/
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 0); //设置优先级
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); //中断使能
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0); //设置优先级
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); //中断使能
/********************************************************************************************************/
在 stm32f1XX_it.c 中查看中断函数
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5); //中断服务函数(此处是指的PA5)可跳转查看定义
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); //中断服务函数(此处是指的PB10)可跳转查看定义
}
/********************************************************************************************************/
/*跳转定义后可以看到:*/
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin); //通过此处跳转至回调函数
}
}
/*跳转至回到函数后可以看到:*/
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //需要重写此虚函数(可复制到主程序中重写)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
/*复制到主程序main.c中重写回调函数:*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin==GPIO_PIN_10) //判断PB10是否触发中断
{
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11); //对端口PA11进行电平反转
}
if (GPIO_Pin==GPIO_PIN_5) //判断PA5是否触发中断
{
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_12); //对端口PA12进行电平反转
}
}