STM32F10X的外部中断(EXTI)
首先,在学习外部中断之前,我们要有一个前要知识,关于NVIC:嵌套向量中断控制器
NVIC寄存器包含如下:
typedef struct {
ISER
ICER
ISPR
ICPR
IABR
IP
STIR
}NVIC_Type;
在配置中断时,我们一般使用ISER、ICER、IP,ISER用来使能中断,ICER用来清除中断,IP用来设置中断优先级
接下来就是如何使用中断
在固件库文件core_cm3.h中,提供了一些NVIC函数 通常库函数编程很少使用,在配置中断可以使用更简洁的方法,我这里以野火作为学习,后面会详细介绍。
IP-中断优先级寄存器介绍 NVIC_IPRx,用来设置外部中断的优先级,该寄存器有8bit,按道理应该有0~255个级别,数字越小,优先级越高,但是为了精简,在103中,高四位用于表达优先级,第四位未使用。
在这高四位中,又分为:抢占优先级、子优先级,抢占优先级级别高于子优先级,简单来说,你想判断中断的优先级,首先比较抢占优先级,如果相同,再比较子优先级,最后比较硬件中断编号,越小越优先。
优先级的分组 在F103中,优先级主要分为5组 主优先级=抢占优先级
设置优先级分组可调用库函数 NVIC_PriorityGroupConfig() 实现,有关 NVIC 中断相关的库函数都在库文件 misc.c 和 misc.h 中。 NVIC_PriorityGroup_0----------0b111 NVIC_PriorityGroup_1----------0b110 NVIC_PriorityGroup_2----------0b101 NVIC_PriorityGroup_3----------0b100 NVIC_PriorityGroup_4----------0b011 中断编程 配置中断主要有三个步骤: 1.使能外设某个中断 2.初始化 NVIC_InitTypeDef 结构体,配置中断源,设置抢占优先级和子优先级,使能中断请求。
typedef struct {
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
NVIC_InitTypeDef 结构体在固件库头文件 misc.h 中定义
中断源:不同的中断,中断源不一样,配置中断源要仔细配置对应中断的中断源,成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type结构体定义
抢断优先级与子优先级:根据优先级分组确定
3.编写中断服务函数 引用野火:
在启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理我们把中断服务函数统一写在stm32f10x_it.c 这个库文件中。
以上才大致认识中断大致流程,接下来才是正式介绍EXTI–外部中断!
EXIT–外部中断/ 事件控制器
EXTI介绍: EXTI:外部中断/ 事件控制器。管理控制器的20个中断/事件线,每个中断/事件线都有一个边沿检测器,上升沿或下降沿检测。通过EXTI可以单独配置这20个中断/事件线,实现我们想要的功能。
EXTI功能图分析 EXTI主要分为两个部分:产生中断、产生事件。 以下为野火STM32库开发实战指南(基于STM32F103)书中详细说明:请务必细心阅读!
首先我们来看图 EXTI 功能框图 中红色虚线指示的电路流程。它是一个产生中断的线路,最终信号流入到 NVIC 控制器内。
编号 1 是输入线, EXTI 控制器有 19 个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个GPIO,也可以是一些外设的事件,这部分内容我们将在后面专门讲解。输入线一般是存在电平变化的信号。 编号 2 是一个边沿检测电路,它会根据上升沿触发选择寄存器 (EXTI_RTSR) 和下降沿触发选择寄存器 (EXTI_FTSR) 对应位的设置来控制信号触发。边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号 1 给编号 3 电路,否则输出无效信号0。而 EXTI_RTSR 和EXTI_FTSR 两个寄存器可以控制器需要检测哪些类型的电平跳变过程,可以是只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。 编号 3 电路实际就是一个或门电路,它一个输入来自编号 2 电路,另外一个输入来自软件中断事件寄存器EXTI_SWIER)。 EXTI_SWIER允许我们通过程序控制就可以启动中断/事件线,这在某些地方非常有用。我们知道或门的作用就是有 1 就为 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等等,这样的脉冲信号一般用来触发 TIM 或者 ADC开始转换。 产生中断线路目的是把输入信号输入到NVIC,进一步会运行中断服务函数,实现功能,这样是软件级的。而产生事件线路目的就是传输一个脉冲信号给其他外设使用,并且是电路级别的信号传输,属于硬件级的。 另外, EXTI 是在 APB2 总线上的,在编程时候需要注意到这点。
中断/时间线 EXTI0-15用于GPIO,可通过编程实现任意GPIO作为外部中断输入源, EXTI0 可以通过 AFIO 的外部中断配置寄存器 1(AFIO_EXTICR1) 的EXTI0[3:0] 位选择配置为 PA0、 PB0、 PC0、 PD0、 PE0、 PF0、 PG0、 PH0 或者 PI0
EXTI初始化结构体详解
EXTI初始化结构体 EXTI_InitTypeDef,用于EXTI_Init() 调用 初始化结构体定义在 stm32f4xx_exti.h 文件中,初始化库函数定义在 stm32f4xx_exti.c 文件中
typedef struct {
uint32_t EXTI_Line;
EXTIMode_TypeDef EXTI_Mode;
EXTITrigger_TypeDef EXTI_Trigger;
FunctionalState EXTI_LineCmd;
} EXTI_InitTypeDef;
EXTI_Line:可选EXTI0~19 EXTI_Mode:可选择产生中断或产生事件 EXTI_Trigger:可选择上升沿或下降沿或者都触发 EXTI_LineCmd:选择使能-ENABLE或禁用-DISABLE
未完待续!
理论部分到此结束,下一节我将会使用示例程序进行详细讲解!
|