qq:78080458 学习交流群:150633458
分类: 嵌入式
2016-07-05 21:35:10
●中断
中断,在单片机中占有非常重要的地位。代码默认地从上向下执行,遇到条件或者其他语句,会按照指定的地方跳转。而在单片机执行代码的过程中,难免会有一些突发的情况需要处理,这样就会打断当前的代码,待处理完突发情况之后,程序会回到被打断的地方继续执行。
●关于STM32的中断
几乎任何一款单片机都会有中断。以STM32F407VE来说,这是一款基于Cortex-M4内核的芯片,在CM4内核中有关于中断的一些管理,在STM32芯片中也有关于中断的一些管理。因此可以总结出一条规律,STM32的中断是有两层控制器分别控制的,如果你想使用中断,那么必须同时配置内核和芯片。
●CM4内核中断
从内核架构图可以看到,NVIC控制器来管理内核中的中断。内核对中断的控制主要表现为几个方面:中断地址、中断优先级、中断使能
1、中断地址
程序的执行无非就是寻找地址,中断也是程序的一部分,而它的地址却是由内核来确定的,而且是不允许修改的。NVIC控制器可以帮我们找到中断的地址
2、中断优先级
优先级在中断里是一个非常重要的概念,如果同时产生多个中断,CPU会根据他们的优先级来选择这些中断的处理顺序。在CM4内核中,优先级用整数来表示,这个数越小代表级别越高。
从CM4内核手册可以看到,复位中断的优先级是最高的,而且不可修改。这一点其实你应该可以猜到,在电脑的世界里,没有什么比复位的级别更高。
NVIC控制器对于优先级的控制分为两级:抢占优先级和子优先级。当多个中断同时发生的时候,抢占优先级高的先执行,如果抢占优先级相同,那么子优先级高的先执行。
抢占优先级和子优先级的设置由一个8位的寄存器(IPR)来决定,NVIC控制器会将这个8位的寄存器分为两半,高位控制抢占优先级,低位控制子优先级。
NVIC控制器中还有一个寄存器(ARICR[10:8])来决定那个8位的优先级寄存器(IPR)如何分成两半,我们知道ARICR[10:8]可以表示0~7,下面的表格给出了ARICR[10:8]与IPR的关系
注意:虽然上图给出了优先级的分组关系,然而在STM32芯片中不会使用优先级寄存器的所有位。例如STM32F407VE使用高4位来表示优先级,假如ARICR[10:8]=5,对照上面的表格可以知道:[7:6]表示抢占优先级[5:4]表示子优先级。对于一个CPU会有N个中断,每个中断的优先级各自可以自由配置,但是中断优先级分组只有一个。例如我们设置STM32F407VE的优先级分组是5,那么所有的中断抢占优先级都是2位控制,子优先级也都是2位控制。
3、中断使能
NVIC对中断有总控的功能,因此这里会有一个开关决定中断功能能否被开启
●STM32外部中断
外部中断只是中断的一种,一般由IO口的电平信号变化而引起。STM32有23个用于产生事件/中断请求的边沿检测器。每根输入线都可以单独配置,可以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发、边沿触发)。每根线还可以单独配置。
1、中断框架
从上图可以看出外部中断的配置方法:
1)打开对应的APB时钟
2)选择外部中断输入线
3)设置中断的触发方式
4)选择工作模式(外部中断、事件)
5)使能
2、外部中断选择
上图列出了外部中断线和GPIO引脚之间的关系,可以总结出外部中断x与GPIOx相连接。例如当我们使用外部中断0的时候,可以配置它与PA0~PI0中的一个或者几个相连
GPIO有16个管脚,总共使用16个外部中断,那么还剩下7个中断在哪里呢?请看下图, 从图中可以了解到另外的7个中断属于“事件”类型
3、寄存器
EXTI_IMR 中断屏蔽寄存器
EXTI_EMR事件屏蔽寄存器
这是中断或者事件的开关,只有对应的位写1,中断或者事件才可以产生作用
EXTI_RTSR 上升沿选择寄存器
EXTI_FTSR 下降沿选择寄存器
这两个寄存器用来选择中断/事件的触发类型,可以是上升沿触发、下降沿触发、边沿触发(上升和下降都可以触发)
EXTI_PR 中断挂起寄存器
这个寄存器是一个标志,如果为1,表示对应的外部中断产生了。需要注意的是,这个寄存器需要手动清零。
●从手册到流程
从上面的叙述可以总结出外部中断的配置方法(其实所有中断配置大同小异)
1、STM32芯片中断设置
1)打开时钟
2)中断引脚选择
3)中断模式选择
4)中断触发方式选择
5)使能中断
2、CM4内核中断配置
1)中断优先级分组(几位表示抢占优先级,几位表示子优先级)
2)设置中断地址
3)设置抢占优先级
4)设置子优先级
5)使能中断
●从流程到代码 (以按钮中断为例,采用库函数)
在使用外部中断的时候,首先确保GPIO处于输入状态,只有输入状态才能保证外部信号进入CPU,从而引发中断。
1、GPIO配置
2、中断配置(有2部分哦)
3、全局中断分组设置,这一句代码需要写在主函数。