如何使用STM32外部中断实现高效响应外部事件?
目录
1.外部中断是什么
想象一个场景:你在家里玩游戏,这时候突然来电话了。这时你会停止玩游戏去接电话,电话打完再放下电话继续玩。这一个过程就体现了中断的思想。我们抽象一下,把自己想象成一个单片机系统,玩游戏就是正在执行的主任务,如果没有外界干扰,这个系统会一直执行当前的主任务。而当外部有改变(电话响了)的时候,系统会第一时间响应,从主任务跳转到这个紧急任务中,这个突发的事件就是(外部)中断,而系统处理的紧急任务则是中断处理函数。当紧急任务(接电话)完毕之后,系统又会回到最初的主任务中。
这就是对中断的简单描述。
定义: 专业说法:中断指的是计算机运行中,正在运行事情被打断,需要紧急处理中断是指一个突发事件,中止了CPU当前的工作,转而处理突发事件,处理完成后再回到当前的工作继续执行。
STM32允许多种多样的中断,如外部IO、ADC、USART、I2C、RTC、USB、PVD等
1. STM32的外部中断线
STM32的每个IO都可以作为外部中断输入。
STM32的中断控制器支持19(20)个外部中断/事件请求:
EXTI0~15:对应外部IO口的输入中断。
EXTI16:连接到PVD输出。
EXTI17:连接到RTC闹钟事件。
EXTI18:连接到USB唤醒事件。
EXTI19 以太网唤醒事件(只适用互联型)
每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。EXTI0 至 EXTI15 用于 GPIO,通过编程控制可以实现任意一个 GPIO 作为 EXTI 的输入源,
EXTI0 可以通过 AFIO 的外部中断配置寄存1(AFIO_EXTICR1) 的 EXTI0[3:0] 位选择配置为 PA0、PB0、PC0、PD0、PE0、PF0、PG0、PH0 或者 PI0。
STM32供IO使用的中断线只有16个,但是STM32F10x系列的IO口多达上百个,STM32F103ZET6(112),STM32F103RCT6(51),那么中断线怎么跟IO口对应上呢?下图就是STM32的外部中断线和IO口的对应关系:
2.NVIC嵌套向量中断器
嵌套向量中断控制器;用于为中断分组,从而分配抢占优先级和响应优先级;只要有中断就必须配置NVIC相关函数。从core_cm3.c及core_cm3.h和misc.c及misc.h中配置NVIC。 对于NVIC,其重要知识点就是优先级分组(抢占优先级)和子优先级(响应优先级),STM32F1XX和STM32F4XX都只使用了8位寄存器的高四位[7:4] (1).抢占优先级和响应优先级的联系和区别(重要原则): 1.高优先级的抢占优先级可以打断正在进行的低抢占优先级中断的
2.抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断
3.抢占优先级相同的中断,当两个中断同时发生的情况下,哪一个的响应优先级高,哪个先执行
4.如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行哪个中断
先占优先级也就是抢占优先级,概念等同于51单片机中的中断。假设有两中断先后触发,已经在执行的中断先占优先级如果没有后触发的中断 先占优先级更高,就会先处理先占优先级高的中断。也就是说又有较高的先占优先级的中断可以打断先占优先级较低的中断。这是实现中断嵌套的基础。 次占优先级,也就是响应优先级,只在同一先占优先级的中断同时触发时起作用,先占优先级相同,则优先执行次占优先级较高的中断。次占优先级不会造成中断嵌套。 如果中断的两个优先级都一致,则优先执行位于中断向量表中位置较高的中断。
下面两张图分别为分组:
NVIC代码配置:
NVIC代码配置: 一、配置分组: NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);//上面有分组状态 二、NVIC初始化: NVIC_InitTypeDef NVIC_InitStruct; //定义结构体变量 NVIC_InitStruct.NVIC_IRQChannel=EXTI9_5_IRQn; //中断线选择中断源 NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能中断 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级 2 NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; //子优先级(响应优先级) 2 NVIC_Init(& NVIC_InitStruct);
外部中断、事件控制器(EXTI):
STM32F1支持将所有GPIO设置为中断输入。外部IO可由上沿、下沿、高低电平的三种方式触发。可选择中断或事件触发。
中断开启过程:
主要过程:中断——分组——具体中断设置到组里面 1.在RCC里将要使用的IO口时钟和复位时钟打开 2.在GPIO里将该IO口映射到相对应的外部中断 3.在NVIC里将该中断通道打开
EXTI库函数:
EXTI Delnit 将外设EXTI寄存器 设为缺省值 EXTI Init 根据EXTIInitStruct中指定的参数初始化外设EXTI寄存器 EXTI_Structlnit 把 EXTIInitStruct中的每一个参数按缺省值填入 EXTI GenerateSWInterrupt 产生一个软件中断 EXTI_GetFlagStatus 检查指定的EXTI线路标志位设置与否 EXTI_ClearFlag 清除 EXTI 线路挂起标志位 EXTI GetlTStatus 检查指定的EXTI线路触发请求发生与否 EXTI_ClearlTPendingBit 清除EXTI线路挂起位
STM32CubeMX配置外部中断:
基础配置在这里就不讲解了 ,想了解的请看我的上节文章,里面有详细的介绍;
1 搜索芯片型号
2选择芯片
3创建工程
GPIO_EXIT的6种模式
External Interrupt Mode with Rising edge trigger detection
上升沿触发外部中断
Extenal Interrupt Mode with Falling edge trigger detection
下降沿触发外部中断
External Interrupt Mode with Rising/Falling edge trigger detection
上升/下降沿触发外部中断
Extenal Event Mode with Rising edge trigger detection
上升沿触发外部事件
Extermal Event Mode with Falling edge trigger detection
下降沿触发外部事件
External Event Mode with Rising/Falling edge trigger detection
上升沿/下降沿触发外部事件
根据自己的需要选择
不用选择 默认就好。
设置NVIC(嵌套向量中断控制器)
1点击NVIC2 勾选EXIT Line
2 interrupt 和 EXIT Line[15:10] interrupt 使能中断
根据前面所讲的 配置你想要的抢占优先级和响应优先级,(不配置也行)
然后再进行时钟树的配置,以及项目文件的设置,这些在上一次的文章中都有写到,如果不会的话,请大家移步到上一次的文章。
ok,现在cubeMX的配置就到这里 ,然后点击生成工程文件,随后我们可以在stm32f1xx_it.c中看到我们所配置的中断服务函数
这里有一个HAL_GPIO_EXTI_IRQHandler();函数
点击右键 Go To Definition 查看一下函数代码
和我们库函数配置差不多,就是清除中断标志位,之后进入中断回调函数中
在HAL库中,中断运行结束后不会立刻退出,而是会先进入相对应的中断回调函数,处理该函数中的代码之后,才会退出中断,所以在HAL库中我们一般将中断需要处理代码放在中断回调函数中。
好了,这就是全部内容了。谢谢大家的观看!!