1 中断系统
1.1 中断简介
中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
比如:对于外部中断而言,可以是引脚电平发生跳变;对于定时器而言,可以是定时事件到了。对于串口通信而言,可以是接收到了数据。
中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。(自己设置的)
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。
1.2 中断流程图
程序由硬件电路自动跳转到中断程序。
保存现场,还原现场(使用C语言编程不用我们考虑,操作系统做)
正常情况下,程序在主函数中执行,当中断条件满足时,主程序会暂停,然后自动跳转到中断程序;当中断程序执行完后,再返回主程序继续执行。一般中断程序都是在一个子函数的,这个函数不需要我们调用,当中断来临时,由硬件自动调用这个函数。
1.3 STM32的中断
68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设。
(中断通道就是中断源的意思)
EXTI:外部中断
TIM:定时器
ADC:模数转换器
USART:串口
SPI通信
I2C通信
RTC实时时钟
使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级
灰色的是内核中断。比如第一个:复位中断,当产生复位中断时,程序就会自动执行复位中断函数。
外部中断对应的中断资源
|----|----|-----|-------|----------|-------------|
| 6 | 13 | 可设置 | EXTI0 | EXTI线0中断 | 0x0000_0058 |
| 7 | 14 | 可设置 | EXTI1 | EXTI线1中断 | 0x0000_005C |
| 8 | 15 | 可设置 | EXTI2 | EXTI线2中断 | 0x0000_0060 |
| 9 | 16 | 可设置 | EXTI3 | EXTI线3中断 | 0x0000_0064 |
| 10 | 17 | 可设置 | EXTI4 | EXTI线4中断 | 0x0000_0068 |
|----|----|-----|---------|----------------|-------------|
| 23 | 30 | 可设置 | EXTI9_5 | EXTI线[9:5]中断 | 0x0000_009C |
|----|----|-----|-----------|------------------|-------------|
| 40 | 47 | 可设置 | EXTI15_10 | EXTI线[15:10]中断 | 0x0000_00E0 |
最右边是地址,因为中断函数的地址由编译器来分配的,它是不固定的,但是中断跳转,由于硬件的限制,只能跳转到固定的地址执行程序,所以为了能让硬件跳转到一个不固定的中断函数中,这里需要在内存中定义一个地址的列表,这个列表地址是固定的,中断发生后,就跳转到这个固定的位置。然后这个固定位置由编译器,再加上一条跳转 到中断函数的代码,这样中断跳转就可以跳转到任意位置了。这个中断地址的列表就叫中断向量表。(相当于中断跳转的跳板,使用C语言编程不需要关心)
1.4 NVIC的基本结构
**NVIC:Nest Vector Interrupt Controller,嵌套中断向量控制器,是用来管理中断嵌套的,核心任务在于其优先级的管理。**NVIC给每个中断赋予先占优先级(抢占优先级)和次占优先级(响应优先级)。
NVIC是内核外设,是CPU的小助手。
一个外设可能会同时占用多个中断通道,所以有n条线。
NVIC只有一个输出口,NVIC根据每个中断的优先级分配中断的先后顺序,之后通过一个输出口告诉CPU该处理哪个中断(医生-CPU,叫号系统-NVIC)
1.5 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 |
值越小,优先级越高,0是最高优先级。
分组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;
数值小的优先响应。
1.6 EXTI外部中断
- EXTI(Extern Interrupt)外部中断;
- EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序;
- 支持的触发方式:上升沿(低->高)/下降沿/双边沿/软件触发;
- 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断(PA0和PB0不能同时用);
- 通道数:16个GPIO_Pin(0-15),外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒;
- 触发响应方式:中断响应/事件响应。
中断响应:申请中断,让CPU执行中断函数;
事件响应:STM32对外部中断新增的额外功能;当外部中断检测到引脚电平变化时,正常的流程是选择触发中断,但是在STM32中也可以选择触发一个事件。如果选择触发事件,那外部的中断信号就不会通向CPU了,而是通向其他外设,用来触发其他外设的操作,比如触发ADC转换,触发DMA等。
总结:中断响应是正常的流程,引脚电平变化触发中断
事件响应不会触发中断,而是触发别的外设操作,属于外设间的联合工作
外部中断有个功能,就是从低功耗模式的停止模式下唤醒STM32;对于PVD电压电压检测,当电源从电压过低恢复时,就需要PVD借助外部中断退出停止模式;对于RTC闹钟而言,有时候为了省电,RTC定一个闹钟之后,STM32会进入停止等待模式,等到闹钟响的时候再唤醒,这也需要借助外部中断。