STM32F4的中断

NVIC

NVIC是嵌套向量中断控制器,主要负责整个芯片有关中断的相关功能,与内核紧密耦合,是内核的一个外设。
但是各个芯片厂商在设计芯片的时候会对Cortex-M4里面的NVIC进行裁剪。

NVIC寄存器简介

NVIC中有多个寄存器都是为中断服务的。
一般我们使用的有ISER、ICER、IP。ISER是用来使能中断。ICER是用来失能中断。IP用来设置中断优先级。

NVIC中断配置固件库

固件库文件core_cm4.h提供了NVIC的一些函数。
比如使能中断 void NVIC_EnableIRQ(IQRn_Type IRQn);
这些库函数我们在编程的时候用的比较少。

优先级的概念

优先级定义

在NVIC中有一个中断优先级寄存器NVIC_IPRx,用于配置外部中断的优先级。IPR宽度为8位,原则上每个外部中断可配置优先级为0~255,数值越小,优先级越高。但是F4中只使用了高四位。
在这里插入图片描述

用于表达优先级的这四位,有被分组为抢占优先级和子优先级。如果有多个中断同时响应,则会先判断抢占优先级,再判断子优先级。如果这两者都相同,则会判断硬件中断编号,编号越小,优先级越高。

优先级分组

优先级分组由外设SCB的应用程序中断以及复位控制寄存器AIRCR的PRIGROUP[10:8]位决定,共分为5组,主优先级就是抢占优先级。
有关NVIC中断有关的库函数都在misc.c和misc.h中
设置优先级分组可调用库函数
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroupx)

中断编程

设置每个中断时一般有3个要点
1、使能某个外设中断,这个具体由每个外设的相关中断使能位控制。
2、初始化NVIC_InitTypeDef结构体,设置中断优先级分组,设置抢占优先级和子优先级,使能中断请求。

typedef struct
{
  uint8_t NVIC_IRQChannel;    //中断源  
    //具体成员配置可参考stm32f4xx.h头文件里面的IRQn_Type结构体定义
  uint8_t NVIC_IRQChannelPreemptionPriority;  //抢占优先级  
  uint8_t NVIC_IRQChannelSubPriority;         //子优先级
  FunctionalState NVIC_IRQChannelCmd;         //中断使能或使能
} NVIC_InitTypeDef;
 static void NVIC_Configuration(void) {     
 NVIC_InitTypeDef NVIC_InitStructure;

 /* 配置 NVIC 为优先级组 1 */
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
 /* 配置中断源:按键 1 */
 NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
 /* 配置抢占优先级: 1 */
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
 /* 配置子优先级: 1 */
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 /* 使能中断通道 */
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     
 NVIC_Init(&NVIC_InitStructure);
}

3、编写中断服务函数
中断服务函数统一写在stm32f4xx_it.c这个库文件。
中断服务函数的函数名必须和启动文件startup_stm32f40xx.s里面预先设置的一样。

EXTI-外部中断/事件控制器

EXTI简介

EXTI管理了控制器的23个中断/事件线,每个中断/事件线都有一个边沿检测器,实现上升沿或者下降沿检测,EXTI可以对它们进行单独控制,配置为中断或者事件,以及触发的属性。

EXTI功能框图

在这里插入图片描述

EXTI共有23个中断/事件输入线,它们可以设置成为任意一个GPIO或者一些外设的事件。
边沿检测电路与上升/下降沿触发选择寄存器电路配合来控制信号触发,通过设置,可以实现上升沿触发、下降沿触发以及上升下降沿都触发。
边沿检测电路接下来进入到一个或电路。软件中断寄存器允许我们通过程序控制启动中断/事件线。或门有一则一,这两个输入源有一个输出1,则会有信号通过或门。
1、出了或门,往上方走是产生中断线路,则先是一个与门,与门另外一个输入是中断屏蔽寄存器,其主要作用就是屏蔽或开放外部中断请求。与门有0则0,所以,只有中断屏蔽寄存器置一时,也就是开放中断请求时,通过或门输入来的信号才会起到作用。然后输出信号会被保存到挂起寄存器中,与门输出为一就会把对应位置1.最终将挂起寄存器的内容输出到NVIC中,从而实现系统中断事件配置。
2、出了或门,往下方走是产生事件线路,先是一个与门,与门的另外一个输入时事件屏蔽寄存器,只有其对应位置1时,输出信号才由或门出来的信号控制,接下来到达脉冲发生器电路,当其输入信号为1时,就会产生一个脉冲。产生事件的最终的脉冲信号可以提供给其他外设电路使用。

中断/事件线

EXTI共有23个中断/事件线,每个GPIO都可以被设置成输入线,占用EXTI 0~EXTI15,另外7根用于特定的外设信号。
在这里插入图片描述

EXTI初始化结构体详解

 typedef struct {
	uint32_t EXTI_Line; // 中断/事件线 可选择EXTI0~EXIT22
	EXTIMode_TypeDef EXTI_Mode; // EXTI 模式 选择为产生中断/事件
	EXTITrigger_TypeDef EXTI_Trigger; // 触发事件 上升沿触发、下降沿触发,上升下降都触发
	FunctionalState EXTI_LineCmd; // EXTI 控制  是否使能EXTI线   ENABALE/DISABLE
} EXTI_InitTypeDef;

外部中断实例

关于外部中断的实际使用主要是有以下几个核心点。
1、开启GPIO时钟和SYSCFG时钟
2、配置GPIO
3、配置NVIC
4、配置EXTI将GPIO连接到EXTI源输入
5、编写EXTI中断服务函数

static void NVIC_Configuration(void) {
	NVIC_InitTypeDef NVIC_InitStructure;

 /* 配置 NVIC 为优先级组 1 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

 /* 配置中断源:按键 1 */
	NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
 /* 配置抢占优先级: 1 */
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
 /* 配置子优先级: 1 */
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
 /* 使能中断通道 */
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}
void EXTI_Key_Config(void){
    /*
    1、定义两个初始化结构体
	2、开启GPIO以及SYSCFG时钟
	3、配置NVIC
	4、配置GPIO结构体并初始化
	5、利用SYSCFG_EXYILineConfig连接中断源
	6、配置EXTI结构体并初始化
	
    */
 /*定义GPIO以及EXTI初始化结构体*/
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;

 /*开启按键 GPIO 口的时钟*/
	RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);
 /* 使能 SYSCFG 时钟 ,使用 GPIO 外部中断时必须使能 SYSCFG 时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

 /* 配置 NVIC */
	NVIC_Configuration();

 /* 选择按键 1 的引脚 */
	GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
 /* 设置引脚为输入模式 */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
 /* 设置引脚不上拉也不下拉 */
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 /* 使用上面的结构体初始化按键 */
	GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

 /* 连接 EXTI 中断源 到 key1 引脚 */
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);

 /* 选择 EXTI 中断源 */
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
 /* 中断模式 */
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
 /* 下降沿触发 */
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
 /* 使能中断/事件线 */
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
}    
void KEY1_IRQHandler(void)
{
 	//确保是否产生了 EXTI Line 中断
	if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {


 	//清除中断标志位
 	EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
 }
}

中断服务函数写在stm32fxx_it.h文件中

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值