STM32外部中断

实践内容:以STM32F407开发板为例,将摁下按键Key_0和Key_1作为中断源来控制LED灯的亮与灭。

KEY原理图

STM32外部中断_第1张图片

由原理图可知:控制按键Key_0和Key_1的GPIO端口是GPIOE,引脚是PE4和PE3。

LED原理图见文章:http://t.csdnimg.cn/owJuB

 中断的概念

在主程序的运行过程中,当有特定的事件发⽣时,CPU暂停正在执行的程序,保留现场后⾃动地
转去执行该事件,执行完成后⼜返回原来被暂停的位置继续运行。

事件的发出者--------中断源

此次事件本身-------中断

中断优先级

当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进⾏裁决,优先响应更加紧
急的中断源。由此也就出现了中断的嵌套

中断的嵌套

当⼀个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断
程序,转而去处理新的中断程序,处理完成后依次进行返回 。如图:

STM32外部中断_第2张图片

内部中断与外部中断

内部中断:由处理器或者程序内部产生的中断。这些中断通常是由于执行指令时产生的错误、特殊条件或程序中的其他异常引起的。

例子:除零错误、溢出错误等。

外部中断:由外部设备或硬件产生的中断。这些中断是来自处理器之外的信号,通常来自设备(如键盘、鼠标、定时器、IO 端口等)。我们平常说的中断是指外部中断。

例子:按下键盘的某个键、鼠标移动、定时器到时等。

中断响应与事件响应

 STM32外部中断_第3张图片

中断响应:某个事件发⽣时,触发了中断,打断了正在执行的CPU,让CPU转而处理此事件。

 事件响应:某个事件发生时,触发了特定的信号,此信号不经过CPU,而是触发了其他外设模块。

核心区分:有无经过CPU

中断的作用和意义

实时响应外部事件

作用:中断机制允许计算机实时响应外部设备的事件,如键盘输入、鼠标移动、定时器到时等。

意义:这确保了计算机可以与外部环境进行交互,使用户能够在需要时与计算机进行实时通信。

提高系统效率

作用:通过允许处理器在必要时暂停当前执行的任务,转而执行中断服务程序,中断提高了系统的效率。

意义:在等待某些事件发生时,处理器可以执行其他任务,从而充分利用计算资源,提高系统整体的效率。

处理异常和错误

作用:中断用于处理各种异常和错误,例如除零错误、溢出错误等。

意义:通过中断机制,计算机可以在出现错误或异常时进行适当的处理,防止系统崩溃或出现不可预测的行为。

NVIC---STM32中断管理控制器

概念

STM32F407具有82个可屏蔽中断通道(就是中断源),10个系统中断。这些中断统一由NVIIC来管理,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组。如图:

STM32外部中断_第4张图片

 NVIC寄存器

typedef struct
{
  __IOM uint32_t ISER[8U];               /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register */
        uint32_t RESERVED0[24U];
  __IOM uint32_t ICER[8U];               /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register */
        uint32_t RESERVED1[24U];
  __IOM uint32_t ISPR[8U];               /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register */
        uint32_t RESERVED2[24U];
  __IOM uint32_t ICPR[8U];               /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register */
        uint32_t RESERVED3[24U];
  __IOM uint32_t IABR[8U];               /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register */
        uint32_t RESERVED4[56U];
  __IOM uint8_t  IP[240U];               /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
        uint32_t RESERVED5[644U];
  __OM  uint32_t STIR;                   /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register */
}  NVIC_Type;

ISER[8](Interrupt Set Enable Register):中断使能寄存器,每个位对应一个中断号,该位设置为 1 表示允许相应的中断。

 ICER[8](Interrupt Clear Enable Registers):中断除能寄存器,每个位对应一个中断号,该位设置为 1 表示禁用相应的中断。

ISPR[8](Interrupt Set Pending Registers):中断使能挂起控制寄存器,通过置 1,可以将
正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。

ICPR[8](Interrupt Clear Pending Registers):中断解除挂起控制寄存器,该位设置为 1 表示清除相应中断的挂起状态。

IABR[8](Interrupt Active Bit Registers):是⼀个中断激活标志位寄存器组。对应位所代表
的中断和 ISER ⼀样,如果为 1,则表示该位所对应的中断正在被执行。这是⼀个只读寄存器,通
过它可以知道当前在执行的中断是哪⼀个。在中断执行完了由硬件自动清零。

IP [240](Interrupt Priority Registers):中断优先级控制寄存器组。由240个8bit的寄存器
组成,每个可屏蔽中断占⽤8bit。但我们只⽤IP[81] - IP[0]这82个。并且,每个中断通道占用的8bit并没有全部使用,而是只用了高4位(2^4=16,这也是有16个优先级的原因)。

NVIC优先级分组

 由于每个中断通道占用的8bit并没有全部使用,而是只用了高4位,我们对这4位又进行了划分,分为⾼n位的抢占优先级和低4-n位的响应优先级。

组别 抢占优先级 响应优先级
分组0 0位,取值为0 4位,取值为0~15
分组1 1位,取值为0~1 3位,取值为0~7
分组2 2位,取值为0~3 2位,取值为0~3
分组3 3位,取值为0~7 1位,取值为0~1
分组4 4位,取值为0~15  0位,取值为0

抢占优先级:高抢占优先级可以打断正在执行的低抢占优先级。

响应优先级:当抢占优先级相同时,响应优先级高(数值小)先执行,但是不能互相打断。

抢占优先级和响应优先级相同的,按中断号(中断向量表)先后执行。

NVIC的配置

STM32外部中断_第5张图片

NVIC_IRQChannel:中断源/中断通道。

NVIC_IRQChannelPreemptionPriority:抢占优先级。

NVIC_IRQChannelSubPriority:响应优先级。

NVIC_IRQChannelCmd:使能中断,由于NVIC属于内核中的器件,默认时钟也是开启的,所以大部分情况下不需要单独设置使能中断。

EXTI--- 外部中断控制器

概念

EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。如图:

STM32外部中断_第6张图片

支持的触发方式:支持上升沿、下降沿、双边沿、软件触发。

支持的响应方式:事件响应 中断响应。

工作原理

STM32外部中断_第7张图片

 

EXTI外设和NVIC之间的关系 

STM32外部中断_第8张图片

 SYSCFG

主要用于管理对可执行代码的存储区域的地址重映射、选择以太网 PHY 接口以及管理 GPIO 的外部中断线连接。STM32 系列的SYSCFG寄存器通常包含EXTICR寄存器用于配置外部中断线的引脚映射,可以通过引脚的高低电平变换来确定中断的来源。

我们将EXTI0 -EXTI15称为中断标志。

 EXTI的配置

STM32外部中断_第9张图片 

EXTI_Line:中断通道,根据中断源的引脚选择(EXTI_Line0~EXTI_Line15)。

 EXTI_Mode:响应模式。

typedef enum
{
  /*中断*/
  EXTI_Mode_Interrupt = 0x00,
  /*事件*/
  EXTI_Mode_Event = 0x04
}EXTIMode_TypeDef;

EXTI_Trigger:触发方式。

typedef enum
{
  /*上升沿*/
  EXTI_Trigger_Rising = 0x08,
  /*下降沿*/
  EXTI_Trigger_Falling = 0x0C,  
  /*双边沿*/
  EXTI_Trigger_Rising_Falling = 0x10
}EXTITrigger_TypeDef;

EXTI_LineCmd:中断使能,EXTI外设的时钟默认是开启的,所以大部分情况下不需要单独设置使能中断。

实践

#include "stm32f4xx.h"                  // Device header

void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3)==SET)
	{
		GPIO_SetBits(GPIOF,GPIO_Pin_9);
		GPIO_SetBits(GPIOF,GPIO_Pin_10);
		
		/*这个是清除中断标志位的函数,否则CPU将陷在中断函数中出不来*/
		EXTI_ClearITPendingBit(EXTI_Line3);
	}
}

void EXTI4_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line4)==SET)
	{
		GPIO_ResetBits(GPIOF,GPIO_Pin_10);
	    GPIO_ResetBits(GPIOF,GPIO_Pin_9);
		EXTI_ClearITPendingBit(EXTI_Line4);
	}
}

int main()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//点灯使能
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);//按键使能
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
	
	//初始化LED灯
	GPIO_InitTypeDef GPIO_InitTypeDefStruct;//点灯结构体
	GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_10;
    GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Fast_Speed;
	GPIO_SetBits(GPIOF,GPIO_Pin_10);
	GPIO_SetBits(GPIOF,GPIO_Pin_9);//灭
	GPIO_Init(GPIOF,&GPIO_InitTypeDefStruct);

	//初始化按键
	GPIO_InitTypeDef GPIO_Struct2;//按键结构体1
	GPIO_Struct2.GPIO_Mode = GPIO_Mode_IN;
	GPIO_Struct2.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3;//按键
	GPIO_Struct2.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Struct2.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOE,&GPIO_Struct2);

    //配置SYSCFG
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);

    //配置EXTI
	EXTI_InitTypeDef EXTI_InitStructure1;//EXTI1 结构体
	EXTI_InitStructure1.EXTI_Line=EXTI_Line3;
	EXTI_InitStructure1.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure1.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure1.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure1);
	
	EXTI_InitTypeDef EXTI_InitStructure2;//EXTI2 结构体
	EXTI_InitStructure2.EXTI_Line=EXTI_Line4;
	EXTI_InitStructure2.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure2.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_InitStructure2.EXTI_LineCmd=ENABLE;
	EXTI_Init(&EXTI_InitStructure2);
	
	//配置NVIC
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2);
	NVIC_InitTypeDef  NVIC_InitStructure1;//NVIC1 结构体
	NVIC_InitStructure1.NVIC_IRQChannel=EXTI3_IRQn;
	NVIC_InitStructure1.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure1.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure1);
	
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2);
	NVIC_InitTypeDef  NVIC_InitStructure2;//NVIC2 结构体
	NVIC_InitStructure2.NVIC_IRQChannel=EXTI4_IRQn;
	NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStructure2.NVIC_IRQChannelSubPriority=1;
    NVIC_Init(&NVIC_InitStructure2);
	
	while(1)
	{
		EXTI3_IRQHandler();
		EXTI4_IRQHandler();
	}

}

运行结果:按下key0,LED灯亮,按下key1,LED灯灭。

你可能感兴趣的:(STM32,stm32,嵌入式硬件,单片机)