STM32 外部中断
中断系统
-
中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
- 中断就是在正常主程序执行的某个时刻,发生了中断触发条件,比如对于外部中断来说,可以是引脚发生了电平跳变,对于定时器来说,可以是定时时间到了。当这些事件发生时,情况比较紧急,比如外部中断来了,如果不及时处理,下一个跳变信号就跟着过来了。比如串口接收中断来了,如果不及时读取接收到的数据,那下一个数据再过来,就会把原来的数据覆盖掉。
- 所以我们希望当中断满足条件时,CPU能够立刻停下当前执行的程序,转而去处理这些中断事件的程序。比如,外部中断来了,我想要计次,那就变量++,串口中断来了,我就把接收到的数据转存起来。当这些紧急事件处理完成后,CPU还能回到原来停下的地方继续运行。
- 使用中断系统,能够极大地提高程序的效率,比如如果没有中断系统,为了防止外部中断被忽略或者串口数据被覆盖,那主程序就只能不断地查询是否有这些事件发生,不能再干其他事情了。比如没有定时器中断,那主程序只有靠Delay函数,才能实现定时的功能。但有了中断系统之后,主程序就可以放心执行其他事情,有中断的时候再去处理,这样效率就会大大提升。
-
中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
- 中断优先级是根据程序设计的要求,自己设置的,中断优先级是为了在多个中断同时申请时,判断一下,应该先处理哪个,如果事件非常紧急,那就把优先级设置高一些,如果不是那么紧急,那就可以把优先级设置低一些,这样可以更好地安排这些中断事件,防止紧急的事件被别的中断耽误。
-
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回
- 这种把中断程序再次中断的现象,就叫做中断嵌套,中断嵌套也是为了照顾非常紧急的中断的,如果CPU已经在执行某个中断程序了,这时又发生了一个非常紧急的中断,那这个中断就可以把当前的中断程序进行二次中断,这样新的紧急中断就可以立即被执行了。能否进行中断嵌套,也是由中断优先级来决定的。
中断执行流程
STM32中断
-
68个可屏蔽中断通道(中断源),包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设
-
使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级
NVIC基本结构
-
NVIC嵌套中断向量控制器,用来统一分配中断优先级和管理中断的,NVIC是一个内核外设,是CPU的小助手。
- STM32的中断非常多,如果把这些中断全部接到CPU上,那PCU还得引出很多线进行适配,设计上就很麻烦,并且如果很多中断同时申请,或者中断很多产生了拥堵,CPU也会很难处理,毕竟CPU主要是用来运算的。
- NVIC有很多输入口,有多少个中断线路,都可以接过来,比如这里可以接到EXTI、TIM、ADC、USART等等。
/n表示一个外设可能会同时占用多个中断通道,所以这里有n条线。然后,NVIC只有一个输出口,NVIC根据每个中断的优先级分配中断的先后顺序。之后,通过这一个输出口告诉CPU你该处理哪个中断。对于中断先后顺序分配的任务,CPU不需要知道。
NVIC优先级分组
-
NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
-
抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队
分组方式 | 抢占优先级 | 响应优先级 |
---|---|---|
分组0 | 0位,取值为0 | 4位,取值为0~15 |
分组1 | 1位,取值为0~1 | 3位,取值为0~7 |
分组2 | 2位,取值为0~3 | 2位,取值为0~3 |
分组3 | 3位,取值为0~7 | 1位,取值为0~1 |
分组4 | 4位,取值为0~15 | 0位,取值为0 |
EXTI简介
-
EXTI(Extern Interrupt)外部中断
-
EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
-
支持的触发方式:上升沿/下降沿/双边沿/软件触发
-
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断
- 比如PA0和PB0不能同时使用,或者PA1、PB1、PC1这样的,端口GPIO_Pin一样的,只能选1个作为中断引脚。所以如果有多个中断引脚,要选择不同Pin的引脚。比如PA6和PA7、PA9和PB15、PB0和PB1这样的都可以。
-
通道数:16个GPIO_Pin(对应GPIO_Pin_0~GPIO_Pin_15),外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒,总共20个中断线路。
- 外部中断可以从低功耗的停止模式下唤醒STM32。
- 对于PVD电源电压检测,当电源从电压过低恢复时,就需要PVD借助一下外部中断退出停止模式。
- 对于RTC闹钟来说,为了省电,RTC定一个闹钟之后,STM32会进入停止模式,等闹钟响的时候再唤醒,这也需要借助外部中断。
- USB唤醒、以太网唤醒也是同样的作用。
- 外部中断可以从低功耗的停止模式下唤醒STM32。
-
触发响应方式:中断响应/事件响应
- 如果选择中断响应,就是申请中断,让CPU执行中断函数
- 如果选择事件响应,那外部中断的信号就不会通向CPU了,而是通向其他外设,用来触发其他外设的操作。比如触发ADC转换、触发DMA等。
- 中断响应是正常的流程,引脚电平变化触发中断,事件响应不会触发中断,而是触发别的外设操作,属于外设之间的联合操作。
EXTI基本结构
- GPIO外设,比如GPIOA、GPIOB、GPIOC等等,每个GPIO外设有16个引脚,所以进来16根线。但是EXTI模块只有16个GPIO通道,所以会有一个AFIO中断引脚选择的电路模块。
- AFIO就是一个数据选择器,它可以在GPIO外设的16个引脚里选择其中一个连接到后面EXTI的通道里,所以相同的Pin_x不能同时触发中断,因为PA0,PB0,PC0这些,通过AFIO选择之后,只有其中一个能接到EXTI的通道0上。同理,PA1、PB1、PC1这些,也只能有一个,连接到通道1上。
- 通过AFIO选择之后的16个通道,就接到了EXTI边沿检测及控制电路上。同时PVD、RTC、USB、ETH这四个外设也是并列接进来的。这些加起来,就组成了EXTI的20个输入信号。
- 然后经过EXTI电路之后,分为了两路输出
- 通向NVIC,用于触发中断
- 为了节省资源,外部中断的9~5和15~10,分到了一个通道里,也就是说外部中断的9~5和15~10会触发同一个中断函数。在编程的时候,我们在这两个中断函数里,需要再根据标志位来区分到底是哪个中断进来的。
- 通向其他外设,这就是用来触发其他外设操作的,也就是事件响应。
- 通向NVIC,用于触发中断
AFIO复用IO口
-
AFIO主要用于引脚复用功能的选择和重定义,也就是数据选择器的作用
-
在STM32中,AFIO主要完成两个任务:复用功能引脚重映射(将默认复用功能的引脚转换到重定义的位置上来)、中断引脚选择
EXTI框图
- 20根输入线首先进入边沿检测电路,在上面的上升沿寄存器和下降沿寄存器可以选择是上升沿触发还是下降沿触发或者双边沿触发。
- 接着触发信号进入到或门的输入端,同时,软件中断事件寄存器也接在或门上,也就是任意一个为1,或门就可以输出1。
- 触发信号通过或门后,兵分两路
- 一路触发中断,触发中断首先会置一个请求挂起寄存器,相当于一个中断标志位,我们可以读取这个寄存器判断是哪个通道触发的中断,如果中断挂起寄存器置1,就会和中断屏蔽寄存器共同进入一个与门,然后至NVIC中断控制器。这里的与门实际上就是开关的作用,中断屏蔽寄存器给1,那请求挂起寄存器的输入就是直接输出,也就是允许中断。相反,中断屏蔽寄存器给0,就是不允许中断。
- 一路触发事件,事件屏蔽寄存器进行开关控制,最后通过一个脉冲发生器,到其他外设。脉冲发生器就是给一个电平脉冲,用来触发其他外设的动作。
/20表示20根线,也就是20个通道,上面是外设接口和APB总线,我们可以通过总线访问这些寄存器。