STM32F407学习笔记(1)-EXTI中断事件与NVIC寄存器

EXTI中断实验

1、实验目的:控制按键KEY1、KEY2触发中断,进入中断服务函数使 LED1和LED二分别状态反转。

2、实验步骤:

1、使能中断:即就是配置EXTI(将按键GPIOA_0和GPIOC_13分别接到EXTI的 EXTI_Line0和 EXTI_Line13上)
2、配置中断优先级分组(NVIC_PriorityGroupConfig函数实现)
3、配置NVIC寄存器(主要是配置中断源,本实验中断源是EXTI0_IRQn和 EXTI15_10_IRQn)
4、编写中断服务函数(本实验通过EXTI_GetITStatus获取终端是否产生从而控制LED状态反转)
5、在main函数里调用各个初始化函数

3、EXTI相关知识以及库函数操作

1、STM32F4 的每个 IO 都可以作为外部中断的中断输入口,STM32F407 的中断控制器支持 22个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F407 的 22 个外部中断为:

     // EXTI 线 0~15:对应外部 IO 口的输入中断。
     //EXTI 线 16:连接到 PVD 输出。
     //EXTI 线 17:连接到 RTC 闹钟事件。
     // EXTI 线 18:连接到 USB OTG FS 唤醒事件。
     //EXTI 线 19:连接到以太网唤醒事件。
     //EXTI 线 20:连接到 USB OTG HS(在 FS 中配置)唤醒事件。
     // EXTI 线 21:连接到 RTC 入侵和时间戳事件。
     //EXTI 线 22:连接到 RTC 唤醒事件

从上面可以看出, STM32F4 供 IO 口使用的中断线只有 16 个,但是 STM32F4 的 IO 口却远远不止 16 个,那么 STM32F4 是怎么把 16 个中断线和 IO 口一一对应起来的呢?于是 STM32就这样设计, GPIO 的管教 GPIOx.0~GPIOx.15(x=A,B,C,D,E, F,G,H,I)分别对应中断线 0~15。这样每个中断线对应了最多 9 个 IO 口,以线 0 为例:它对应了 GPIOA.0、 GPIOB.0、 GPIOC.0、GPIOD.0、 GPIOE.0、 GPIOF.0、 GPIOG.0,GPIOH.0,GPIOI.0。而中断线每次只能连接到 1 个 IO口上,这样就需要通过配置来决定对应的中断线配置到哪个 GPIO 上了。具体的EXTI与GPIO映射关系如下图
在这里插入图片描述2、初始化EXTI,设置 IO 口与中断线的映射关系
第一步:开启EXTI SYSCFG 时钟,使用库函数RCC_APB2PeriphClockCmd具体参考STM32F4XX中文参考手册

第二步:配置 GPIO 与中断线的映射关系:使用库函数 SYSCFG_EXTILineConfig实现;例如将中断线 0 与 GPIOA 映射起来SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
第三步:初始化EXTI线上中断,设置触发条件等
本实验设置 EXTI_Line0和EXTI_Line13的触发模式(通过EXTI_InitTypeDef定义一个结构体变量设置中断源,中断触发模式,使能中断事件然后赋值然后再由初始化函数EXTI_Init(&EXTI_InitStructure)写入相关寄存器)

4、NVIC分组以及NVIC初始化

CM4内核支持256个中断,其中包含16个内核中断和240个外设中断,并且具有256级的可屏蔽中断设置。STM32F4只使用了内核中断的一部分,例如STM32F4XX/STM32F41XX总共有92个中断
STM32F42XX/STM32F43XX总共有96个中断。STM32F40XX/STM32F41XX的92个中断中,包括10个内核中断和82个可屏蔽中断,具有16级可编程的中断优先级,而我们常用的就是这82个可屏蔽中断。

中断管理办法:

1、首先对中断进行分组,组0~4.同时对每个中断设置一个抢占优先级和一个响应优先级值。
2、分组的配置在寄存器SCB->AIRCR[10:8]中设置(参考内核手册),确定分组的时候一般只设置一次(否则会引起混乱),数值越低,优先级越高。具体实现方式是通过分组库函数 NVIC_PriorityGroupConfig实现分组:misc.c文件 里定义的。
3、高抢占优先级可以打断正在进行的低的抢占优先级。在抢占优先级相同的情况下,高响应优先级不能打断低响应优先级。响应优先级同时发生时由高低决定。
4、对于每一个中断,都对应一个中断优先级控制的寄存器,CM4内核中断优先级控制的寄存器组:IP[240](240个8位的中断优先级控制寄存器组,对应每个中断),STM32F4只用到了IP[81]~IP[0],每个IP寄存器的高四位用来设置抢占优先级和响应优先级,低四位没有用到。
5、开始初始化NVIC,即就是定义一个NVIC_InitTypeDef类型的结构体变量,根据上一步使能的中断源,选择中断源以及中断源优先级设置,使能中断通道,将相关的值给结构体变量赋值,再通过NVIC_Init写入相关寄存器。
6、编写中断服务函数,切记中断服务函数名要与向量表里定义的函数名一致,一般把终端服务函数写在stm32f4xx_it.c文件里。然后再由main函数调用,整个流程就完了。

相关代码以及代码分析

//NVIC初始化,以及中断向量优先级分组相关函数
static void NVIC_Configuration(void)
{
	//定义一个NVIC初始化结构体变量
  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);
  
  /* 配置中断源:按键2,其他使用上面相关配置 */  
  NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
  NVIC_Init(&NVIC_InitStructure);
}

//EXTI中断相关函数:
void EXTI_KEY_Config(void)
{
	//定义两个结构体变量
		GPIO_InitTypeDef GPIO_InitStructure; 
	  EXTI_InitTypeDef EXTI_InitStructure;
	
	/*开启按键GPIO口的时钟*/
	RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK|KEY2_INT_GPIO_CLK ,ENABLE);
	
	/* 选择按键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); 
	
	  /* 选择按键2的引脚 ,其他参数和按键1相同*/ 
  GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;  
  /* 其他配置与上面相同 */
  GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);      
	
	/*第一步:初始化EXTI,中断使能*/
	   /*首先要开启系统配置控制寄存器*/
		 /* 使能 SYSCFG 时钟 ,使用GPIO外部中断时必须使能SYSCFG时钟*/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	/* 连接 EXTI 中断源 到key1引脚,GPIOA端口第0引脚与EXTI相连 */
  SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE,KEY1_INT_EXTI_PINSOURCE);
	
	/* 选择 EXTI 中断源 */
  EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
  /* 中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  /* 下降沿触发 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
  /* 使能中断/事件线 */
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
		/* 连接 EXTI 中断源 到key2 引脚 */
  SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE,KEY2_INT_EXTI_PINSOURCE);
	 /* 选择 EXTI 中断源 */
  EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  /* 下降沿沿触发 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
	
	/*第二、三步调用配置中断优先级分组和初始化NVIC*/
	NVIC_Configuration();
	/*编写中断服务函数*/
	
}
//EXTI初始化函数里面的宏定义
#ifndef __EXTI_H
#define	__EXTI_H

#include "stm32f4xx.h"

//引脚定义
/*******************************************************/
#define KEY1_INT_GPIO_PORT                GPIOA
#define KEY1_INT_GPIO_CLK                 RCC_AHB1Periph_GPIOA
#define KEY1_INT_GPIO_PIN                 GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE          EXTI_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE           EXTI_PinSource0
#define KEY1_INT_EXTI_LINE                EXTI_Line0
#define KEY1_INT_EXTI_IRQ                 EXTI0_IRQn

#define KEY1_IRQHandler                   EXTI0_IRQHandler

#define KEY2_INT_GPIO_PORT                GPIOC
#define KEY2_INT_GPIO_CLK                 RCC_AHB1Periph_GPIOC
#define KEY2_INT_GPIO_PIN                 GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE          EXTI_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE           EXTI_PinSource13
#define KEY2_INT_EXTI_LINE                EXTI_Line13
#define KEY2_INT_EXTI_IRQ                 EXTI15_10_IRQn

#define KEY2_IRQHandler                   EXTI15_10_IRQHandler



void EXTI_Key_Config(void);

#endif /* __EXTI_H */

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值