基于STM32F4实现中断例程


前言

接着上次的流水灯今天来学习中断操作。


一、如何配置中断及其详解

1.中断是什么?

中断就是在程序正常运行时,CPU突然收到更急紧急的事情的时候,这时CPU就需要暂停正在处理的事立马去处理这件更加紧急的事,处理完后再回到原来的事情。中断的过程如下图所示:
在这里插入图片描述

2.中断优先级

这是需要思考一个问题,当多个中断触发时,CPU应该先处理哪一个中断呢?这时我们就需要配置中断优先级,既然都是紧急的事情当然会分哪一个更加紧急。m4中最多支持16个优先级。其中优先级又分为抢占优先级和响应优先级。

2.1 抢占优先级

不管中断产生的先后顺序,只比较抢占优先级的高低,优先级高的立即执行,例如:如果一个中断执行过程中,又有一个更高抢占优先级中断产生,CPU则会暂停当前中断跑去执行更高抢占优先级中断,形成中断嵌套。

2.2 相应优先级

如果两个相同抢占优先级的中断产生,那么两个中断会按照响应优先级顺序进行排队,优先级高的先执行

3.如何配置中断?

我们查看stm32f4的中文参考手册,如下图:
在这里插入图片描述
从图中可以看出我们可以同时配置16个中断。结合开发文档总结出配置的大概思路(今天使用的时PE3和PE4配置两个中断):
1.初始化PE3和PE4引脚。
2.配置外部中断。
3.其中中断不是直接告诉CPU需要处理中断的,而是由中断向NVIC再向CPU申请中断的,所以还要配置NVIC.

二、详细代码

#include "stm32f4xx.h"                  // Device header
#include "sys.h"
GPIO_InitTypeDef  GPIO_InitStructure;
EXTI_InitTypeDef   EXTI_InitStructure;
NVIC_InitTypeDef   NVIC_InitStructure;

void delay(void)
{
    
    
	uint32_t i=0x2000000;
	while(i--);
}

void exti3_init(void)
{
    
    
	//是能端口E硬件时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	//使能系统配置时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	//配置PE3为输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
	//将PE3和exti连接在一起
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
	//外部中断配置
	EXTI_InitStructure.EXTI_Line = EXTI_Line3;//中断引脚
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//触发方式  
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能
    EXTI_Init(&EXTI_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//打开外部中断3的通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能该通道
	NVIC_Init(&NVIC_InitStructure);
}

void exti4_init(void)
{
    
    
	//是能端口E硬件时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	//使能系统配置时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	//配置PE3为输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
	//将PE3和exti连接在一起
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
	//外部中断配置
	EXTI_InitStructure.EXTI_Line = EXTI_Line4;//中断引脚
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//触发方式  
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能
    EXTI_Init(&EXTI_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//打开外部中断3的通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;//响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能该通道
	NVIC_Init(&NVIC_InitStructure);
}
int main(void)
{
    
    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟

	//GPIOF9,F10初始化设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
	
	
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9 |GPIO_Pin_10);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	exti3_init();//exti3的初始化
	exti4_init();
	while(1)
	{
    
    
		

		
	}
}


void EXTI3_IRQHandler(void)
{
    
    
	//判断是否有中断请求
	if(EXTI_GetITStatus(EXTI_Line3) == SET)
	{
    
    
		
		PFout(9)=0;
		delay();
		//清空标志位
		EXTI_ClearITPendingBit(EXTI_Line3);
	}

}

void EXTI4_IRQHandler(void)
{
    
    
	//判断是否有中断请求
	if(EXTI_GetITStatus(EXTI_Line4) == SET)
	{
    
    
		PFout(10)=0;
		delay();
		delay();
		delay();
		PFout(10)=1;
		//清空标志位
		EXTI_ClearITPendingBit(EXTI_Line4);
	}

}


总结

刚开始不是很懂中断,对优先级理解不了,多学习即便多动手反复实验慢慢就懂了。持续学习可以学到更多东西,反复学习可以把所学的的东西学得更有深度,学习真是一个持续且循序渐进的过程。

猜你喜欢

转载自blog.csdn.net/weixin_46155589/article/details/127348393