IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32-外部中断/事件控制器(EXTI)的配置与使用 -> 正文阅读

[嵌入式]STM32-外部中断/事件控制器(EXTI)的配置与使用

????在我们学习STM32时中断是一个必不可少的部分,中断能够帮助我们解决很多问题,下面就让小编给大家展示STM32中断相关知识吧。

一、中断的定义

????中断就是CUP暂时中断正在执行的程序,转而去执行中断请求的外设或者事件的服务程序,待处理完毕中断服务程序后再执行原程序。例如,小明正在看书(CUP的主程序),这时有人打电话给小明,小明就去接这个电话(中断服务函数),接完电话后小明接着去看书(CPU主函数)。

二、中断的作用

1、提高CPU的利用率;
2、具有实时功能;
3、具有故障处理功能;
4、能够实现分时操作;

三、中断处理的过程

中断流程图
第一步,中断响应。这时需要保护现场,并且找到中断对应的中断服务程序的地址,即中断向量表。(一般由硬件自动实现)
第二步,执行中断服务函数。中断服务函数既没有参数,也没有返回值,更不需要用户调用;中断服务函数是中断产生后,才执行的一个函数。(由用户编程)
第三步,中断返回。恢复现场。(由硬件自动实现)

四、STM32F103的中断系统

1、嵌套向量中断控制器NVIC

????向量中断控制器,简称NVIC,访问地址是OxE000_E000,共支持1至240个外部中断输入(通常外部中断写作 IRQs),具体的数值由芯片厂商在设计芯片时决定。此外,NVIC还支持一个“永垂不朽”的不可屏蔽中断(NMI〉输入。所有NVIC的中断控制/状态寄存器都只能在特权级下访问。不过有一个例外——软件触发中断寄存器可以在用户级下访问以产生软件中断。所有的中断控制/状态寄存器均可按字/半字/字节的方式访问。由于NVIC集成在ARM Cortex-M3内核中,与中央处理器核心CM3Core紧密耦合,从而实现低延迟的中断处理和高效地处理晚到的较高优先级的中断。
NVIC中断控制器

  • (1)支持84个异常,包括16个内部异常和68个非内核异常中断;
  • (2)使用4位优先级设置,具有16级可编程异常优先级;
  • (3)中断响应时处理器状态的自动保存,无须额外指令;
  • (4)中断返回时处理器状态的自动恢复,无须额外指令;
  • (5)支持嵌套和向量中断;
  • (6)支持中断尾链技术。

2、STM32F103中断优先级

  • (1)抢占式优先级
    ????高抢占式优先级的中断事件会打断当前的主程序/中断程序运行,俗称中断嵌套。
  • (2) 响应优先级
    ????在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。
  • (3)中断响应依据
    ????首先,比较抢占式优先级;其次,比较响应优先级。是否含有中断嵌套取决于抢占优先级。
  • (4)优先级冲突的处理
    ????具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
    在这里插入图片描述
    STM32F013对优先级的设定

五、函数解析

1、NVIC_DeInit函数

在这里插入图片描述

2、NVIC_Init函数

在这里插入图片描述

3、NVIC_PriorityGroupConfig函数在这里插入图片描述

4、EXTI_Init函数

在这里插入图片描述

5、EXTI_DeInit函数

在这里插入图片描述

6、EXTI_GetITStatus函数

在这里插入图片描述

7、EXTI_ClearFlag函数

在这里插入图片描述

8、GPIO引脚中断映射函数

在这里插入图片描述

六、示例功能

????在STM32F103ZET6开发板上,有五个按键与八个LED灯,现在我们需要按下KEY1点亮LED1、按下KEY2点亮LED2……按下KEY5点亮LED5。

1、中断初始化函数

????在中断初始化函数中,我们需要注意的是GPIO引脚与中断的映射关系。GPIO引脚、外部线路EXTI_Line的值、指定中断通道NVIC_IRQChannel的值都需要一样,不然定义中断就没有效果。例如我们需要使用外部中断6,那么我们就需要选择GPIO_Pin6、EXTI_Line6与EXTI9_5_IRQn。(外部中断的Pin5-Pin9所用的是同一个中断通道。)

void exit_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure; 
	NVIC_InitTypeDef NVIC_InitStructure;
	
	/* 选择GPIOC时钟与时钟复用  */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO , ENABLE);
	
	/* 	GPIO管脚初始化 上拉输入模式  */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
	GPIO_Init(GPIOE, &GPIO_InitStructure); 
	
	/*中断映射 选择GPIO引脚作为外部中断线路 这里一定要给端口引脚加上外部中断线路*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0); 
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource1); 
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2); 
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3); 
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource6); 
	
	 /* 设置外部中断的模式 PE0 PE1 PE2 PE3 PE6中断初始化*/ 
	EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line1|EXTI_Line2|EXTI_Line3|EXTI_Line6;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
	EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
	EXTI_Init(&EXTI_InitStructure); 
	
	//NVIC优先级分组 抢占式优先2位四级 响应式优先级2位四级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	/* 设置 外部中断0 的NVIC参数*/
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //指定中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//配置抢占式优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能
	NVIC_Init(&NVIC_InitStructure); 	
	
	/* 设置 外部中断1 的NVIC参数*/	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //指定中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//配置抢占式优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能
	NVIC_Init(&NVIC_InitStructure); 	
	
	/* 设置 外部中断2 的NVIC参数*/
	NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //指定中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//配置抢占式优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//配置响应式优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能
	NVIC_Init(&NVIC_InitStructure); 	
	
	/* 设置 外部中断3 的NVIC参数*/
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //指定中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//配置抢占式优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//配置响应式优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能
	NVIC_Init(&NVIC_InitStructure); 	
	
	
	/* 设置 外部中断6 的NVIC参数*/
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //指定中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//配置抢占式优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能
	NVIC_Init(&NVIC_InitStructure); 	
}

2、中断响应函数

/**
	* @brief function of exti0(中断0响应函数)
	* @param none
	* @retval none
	*
*/
void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)==SET) 
	{
		EXTI_ClearFlag(EXTI_Line0);//清楚中断EXTI 线路挂起标志位
		//dealy_ms(10);//按键消抖
		if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_0)==Bit_RESET)
		{			
			exit_flag = 1;
		}	
	}
}

/**
	* @brief function of exti1(中断1响应函数)
	* @param none
	* @retval none
	*
*/
void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1)==SET) 
	{
		
		EXTI_ClearFlag(EXTI_Line1);	//清楚中断EXTI 线路挂起标志位	
		//dealy_ms(10);
		if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_1)==Bit_RESET)
		{			
			exit_flag = 2;
		}		
	}
}

/**
	* @brief function of exti2(中断2响应函数)
	* @param none
	* @retval none
	*
*/
void EXTI2_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line2)==SET) 
	{
		EXTI_ClearFlag(EXTI_Line2);//清楚中断EXTI 线路挂起标志位
		//dealy_ms(10);
		if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)
		{				
			exit_flag = 3;
		}	
	}
}

/**
	* @brief function of exti3(中断3响应函数)
	* @param none
	* @retval none
	*
*/
void EXTI3_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line3)==SET) 
	{
		EXTI_ClearFlag(EXTI_Line3);//清楚中断EXTI 线路挂起标志位
		//dealy_ms(10);
		if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==Bit_RESET)
		{			
			exit_flag = 4;
		}	
	}
}

/**
	* @brief function of exti6(中断6响应函数 这里我们只用到了Pin6)
	* @param none
	* @retval none
	*
*/
void EXTI9_5_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line6)==SET) 
	{
		EXTI_ClearFlag(EXTI_Line6);//清楚中断EXTI 线路挂起标志位
		//dealy_ms(10);
		if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6)==Bit_RESET)
		{				
			exit_flag = 5;
		}	
	}
}

3、中断服务函数

extern unsigned char exit_flag;

/**
	* @brief work of exti(中断执行函数)
	* @param none
	* @retval none
	*
*/
void exti_pro(void)
{
	LED_all_off();
	if(exit_flag == 1){//按键1按下 点亮LED1
		LED_ctrl(LED1,LED_ON);
	}else	if(exit_flag == 2){//按键2按下 点亮LED2
		LED_ctrl(LED2,LED_ON);
	}else if(exit_flag == 3){//按键3按下 点亮LED3
		LED_ctrl(LED3,LED_ON);
	}else if(exit_flag == 4){//按键4按下 点亮LED4
		LED_ctrl(LED4,LED_ON);
	}else if(exit_flag == 5){//按键5按下 点亮LED5
		LED_ctrl(LED5,LED_ON);
	}else{//外部中断未响应关闭所有的LED灯
		LED_all_off();
	}
}

4、主函数

int main(void)
{
	LED_GPIO_init();//LED初始化
	key_GPIO_init();//按键初始换化
	exit_Init();//中断初始化
	while(1){
		exti_pro();//中断服务函数
	}
}

七、 附

????假如大家想看相关模块的内容请点击链接前往:STM32-按键STM32-刷新数码管STM32-八位流水灯STM32-配置SysTick定时器

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:39:38  更:2022-07-17 16:42:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 16:23:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码