前言
中断是什么?什么是中断?
在学习 51 单片机时,我们就接触过中断,中断其实就是当 CPU 执行程序时,由于发生了某种随机的事件(外部或内部),引起 CPU 暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序或中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续执行,这一过程就称为中断,引发中断地称为中断源。比如:看电视时突然电话响了,那么电话响就相当于中断源。有些中断还能够被其他高优先级的中断所中断,那么这种情况又叫做中断的嵌套。
正文
那么我们在学习中断的时候,就会必不可少的会涉及到----嵌套向量中断控制器 (NVIC)和外部中断/事件控制器 (EXTI)
NVIC
NVIC:嵌套向量中断控制器,属于内核外设,管理着包括内核和片上所有外设的中断相关的功能。嵌套向量中断控制器 。
stm32F4数据手册上知道
NVIC 包含以下特性:
● STM32F405xx/07xx 和 STM32F415xx/17xx 具有 82 个可屏蔽中断通道,STM32F42xxx 和 STM32F43xxx 具有多达 86 个可屏蔽中断通道(不包括 Cortex™-M4F 的 16 根中 断线)
● 16 个可编程优先级(使用了 4 位中断优先级)
● 低延迟异常和中断处理
● 电源管理控制
● 系统控制寄存器的实现
嵌套向量中断控制器 (NVIC) 和处理器内核接口紧密配合,可以实现低延迟的中断处理和晚 到中断的高效处理。
包括内核异常在内的所有中断均通过 NVIC 进行管理。
在stm32f4xx.cortex-M4手册上有对NVIC寄存器的介绍和讲解
在NVIC当中里面重要的两个库文件core_cm4.h和misc.c文件
在cm4中可以找到关于NVIC相关寄存器即:
在这些寄存器当中最主要的还是优先级的寄存器。
中断优先级寄存器 NVIC_IPRx(在 F407 中,x=0…981)用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。但是绝大多数 CM4 芯片都会精简设计,以致实际上支持的优先级数减少,在F407 中,只使用了高 4bit。用于表达优先级的这 4bit,又被分组成抢占优先级和子优先级。如果有多个中断同时响应,抢占
优先级高的就会抢占抢占优先级低的优先得到执行,如果抢占优先级相同,就比较子优先级。如果抢占优先级和子优先级都相同的话,就比较他们的硬件中断编号,编号越小,优先级越高。
void NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级分组为NVIC_PriorityGroup_1
配置:
在我们要配置NVIC的话,最主要的还是void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)这个函数,这个函数里面初始化结构体:
NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序不会报错,只会导致不会中断。
NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定。
NVIC_IRQChannelSubPriority:子优先级,具体的值要根据优先级分组来确定。
NVIC_IRQChannelCmd:中断使能(ENABLE)或者失能(DISABLE)。
如下所示:
EXTI
EXTI:外部中断/事件控制器 (EXTI) 管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。EXTI 有 23 个中断/事件线,每个GPIO 都可以被设置为输入线,占用 EXTI0 至 EXTI15,还有另外七根用于特定的外设事件。
功能框图:
EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,这两个功能从硬件上就有所不同。首先我们来看图 EXTI 功能框图 中红色虚线指示的电路流程。它是一个产生中断的线路,最终信号流入到 NVIC 控制器内。
编号 1 是输入线,EXTI 控制器有 23 个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个 GPIO,也可以是一些外设的事件,这部分内容我们将在后面专门讲解。输入线一般是存在电平变化的信号。
编号 2 是一个边沿检测电路,它会根据上升沿触发选择寄存器 (EXTI_RTSR) 和下降沿触发选择寄存器 (EXTI_FTSR) 对应位的设置来控制信号触发。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号 1 给编号 3 电路,否则输出无效信号 0。而 EXTI_RTSR 和EXTI_FTSR 两个寄存器可以控制器需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。
编号 3 电路实际就是一个或门电路,它一个输入来自编号 2 电路,另外一输入来自软件中断事件寄存器 (EXTI_SWIER)。EXTI_SWIER 允许我们通过程序控制就可以启动中断/事件线,这在某些地方非常有用。我们知道或门的作用就是有”就为 1,所以这两个输入随便一个有有效信号 1 就可以输出 1 给编号 4 和编号 6 电路。
编号 4 电路是一个与门电路,它一个输入编号 3 电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。与门电路要求输入都为 1 才输出 1,导致的结果如果 EXTI_IMR 设置为 0 时,那不管编号 3 电路的输出信号是 1 还是 0,最终编号 4 电路输出的信号都为 0;如果 EXTI_IMR设置为 1 时,最终编号 4 电路输出的信号才由编号 3 电路的输出信号决定,这样我们可以简单的控制 EXTI_IMR 来实现是否产生中断的目的。编号 4 电路输出的信号会被保存到挂起寄存器(EXTI_PR) 内,如果确定编号 4 电路输出为 1 就会把 EXTI_PR 对应位置 1。
编号 5 是将 EXTI_PR 寄存器内容输出到 NVIC 内,从而实现系统中断事件控制。接下来我们来看看绿色虚线指示的电路流程。它是一个产生事件的线路,最终输出一个脉冲信号。产生事件线路是在编号 3 电路之后与中断线路有所不同,之前电路都是共用的。
编号 6 电路是一个与门,它一个输入编号 3 电路,另外一个输入来自事件屏蔽寄存器 (EXTI_EMR)。如果EXTI_EMR 设置为 0 时,那不管编号 3 电路的输出信号是 1 还是 0,最终编号 6 电路出的信号都为 0;如果 EXTI_EMR 设置为 1 时,最终编号 6 电路输出的信号才由编号 3 电路的输出信号决定,这样我们可以简单的控制 EXTI_EMR 来实现是否产生事件的目的。
编号 7 是一个脉冲发生器电路,当它的输入端,即编号 6 电路的输出端,是一个有效信号 1 时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
编号 8 是一个脉冲信号,就是产生事件的线路最终的产物,这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等。
产生中断线路目的是把输入信号输入到 NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。
注意:EXTI 是在 APB2 总线上的。
配置:配置的主要函数void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);函数结构体:
EXTI_Line:EXTI 中断/事件线选择,可选 EXTI0 至 EXTI22。
EXTI_Mode:EXTI 模式选择,可选为产生中断 (EXTI_Mode_Interrupt) 或者产生事件(EXTI_Mode_Event)。
EXTI_Trigger:EXTI 边沿触发事件,可选上升沿触(EXTI_Trigger_Rising)、下降沿触发(EXTI_Trigger_Falling) 或者上升沿和下降沿都触发 ( EXTI_Trigger_Rising_Falling)。
)EXTI_LineCmd:控制是否使能 EXTI 线,可选使能 EXTI 线 (ENABLE) 或禁用 (DISABLE)。
如下: