STM32的中断操作(一)——EXTI

前言

在单片机的编程中,中断都是很重要的一个概念。在stm32中,中断有两种,一种是外部中断(EXTI),另一种是定时器中断(SysTick),本篇文章从中断的概念入手,再对外部中断简要的做一些介绍。


一、中断是什么?

相信大家在初学中断这个概念时都听过这样一个例子:如果你一个人在家里正在做饭,这时门铃响了,你选择先去开门,然后再回来做饭,这就是一个浅显易懂的中断的例子,做饭为主程序,而去开门就是中断程序,门铃响起就是中断请求。而如果门铃响起同时电话也响起,那么你决定先去处理哪一件事的过程就是中断优先级的判别过程。
中断的定义如下:

中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。

而对于stm32来说:stm32每一个外设都可以产生中断,如无特殊说明,中断就是异常,异常就是中断。

二、中断所需寄存器

1.配置产生中断所需的寄存器

初始化EXTI,应首先调用GPIO.C文件中的EXTI_LINE_CONFIG函数(选择输入线),再查阅stm32官方的中文参考手册找到所要使用的外部中断所处的总线,打开此总线上的时钟。
EXTI_Initstruct有四个成员,分别为:

(1)EXTI_Line:

配置中断数据线,PA0,PB0等配置为Line0,PA1,PB1等配置为Line1,以此类推,如要配置PA1和PC13两个按键引发外部中断则需使能Line1和Line13.

(2)EXTI_Mode:

配置为中断模式时配置为EXTI_Mode_Interrupt.

(3)EXTI_Trigger:

触发方式配置,有raising,falling,raising-falling三个选项,可根据自身需要配置。

(4)EXTI_LineCmd

中断事件屏蔽寄存器,要写成ENABLE来响应中断

		RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
		GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE);
		EXTI_InitStruct.EXTI_Line=KEY1_INT_EXTI_LINE;
	
		EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
		EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;
		EXTI_InitStruct.EXTI_LineCmd=ENABLE;
		EXTI_Init(&EXTI_InitStruct);

2.配置中断优先级

在管理中断优先级时需要用到的部件为嵌套向量中断控制器(NVIC),属于内核外设,管理着包括内核和片上所有外设的中断相关的功能。对其进行描述的头文件为core_cm3.h和misc.h,可查阅stm32F10xxx Cortex-M3编程手册进行详细学习。
优先级包括主优先级和子优先级,主优先级又称抢占优先级,在stm32中用四个位来描述优先级,在这四个位中主优先级和子优先级分别占几位是需要人为配置的,即在上文的中断分组中。在stm32的固件库中,给出了优先级分组和主优先级和子优先级分别占几位的描述。在这里插入图片描述
NVIC中结构体中有四个与配置优先级相关的变量,它们分别为:

(1)NVIC_IRQChannel:中断源

其取值在stm32f10x.h中,其部分可取如下所示:
在这里插入图片描述
若用EXTI0-EXTI4则可分别取EXTI0_IRQn~EXTI4_IRQn,但要注意,若用EXTI5-EXTI9则选择EXTI9_5_IRQn若用EXTI10-EXTI15则用EXTI15_10_IRQn。

(2) NVIC_IRQ_ChannelPreemtionPriority主优先级

根据上文中中断向量表可根据所选中断分组选择合适的主优先级,如选择分组1时,主优先级可配置成0或1,配置的数越小中断优先级越高。

(3)NVIC_IRQ_ChannelSubemtionPriority子优先级

根据上文中断向量表的描述,当选用分组1时,子优先级可配置为0-7中的数,同样为数值越小优先级越高,当主优先级不同时比较主优先级,主优先级相同时再比较子优先级。

(4)NVIC_IRQChannelCmd:总中断开关

根据固件库的描述,若想让中断可用,此成员应配置成ENABLE。

void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
	NVIC_InitStruct.NVIC_IRQChannel=KEY1_INT_EXTI_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

三、外部中断编程步骤

以产生两个按键,PA1,PC13两路外部中断为例

1、初始化中断操作的GPIO

		GPIO_InitTypeDef GPIO_InitStruct;
		GPIO_InitStruct.GPIO_Pin=KEY1_INT_GPIO_PIN;
		GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	  //GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
		GPIO_Init(KEY1_INT_GPIO_PORT,&GPIO_InitStruct)

2、初始化EXTI用于产生中断

#define KEY1_INT_GPIO_PORT          GPIOA
#define KEY1_INT_GPIO_CLK           (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN           GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE    GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE     GPIO_PinSource0
#define KEY1_INT_EXTI_LINE          EXTI_Line0
#define KEY1_INT_EXTI_IRQ           EXTI0_IRQn
#define KEY2_INT_GPIO_PORT          GPIOC
#define KEY2_INT_GPIO_CLK			(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN			GPIO_PIN_13
#define KEY2_INT_GPIO_PORTSOURCE    GPIO_PORT_SourceGPIOC
#define KEY2_INT_GPIO_PINSOURCE	    GPIO_PinSource13
#define KEY2_INT_EXTI_LINE			EXTI_Line13
#define KEY2_INT_EXTI_IRQ			EXTI15_10_IRQn
void EXTI_Key_Config(void);
EXTI_InitTypeDef EXTI_InitStruct;
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
EXTI_InitStruct.EXTI_Line=KEY1_INT_EXTI_LINE;
	
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStruct);

另外一个按键的中断配置与此类似,这里不再赘述。

3、初始化NVIC用于配置中断

void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
	NVIC_InitStruct.NVIC_IRQChannel=KEY1_INT_EXTI_IRQ;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

4、编写中断服务函数

再编写中断服务函数
为了方便管理,中断服务函数都写在stm32f10x_it.c中,注意函数名称要查中断向量表,大约位置在启动文件中第264行以后EXTI0_IRQ_Handler(中断服务函数名) 。如本篇如要编写KEY1(GPIOA_1)的中断服务函数,函数名应取:EXTI0_IRQHandler,要编写KEY2(GPIOC_13)的中断服务函数,函数名应取:EXTI15_10_IRQHandler

void EXTI0_IRQHandler(void)
{

	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
	{	
		LED1_TOGGLE;
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
	}  
}
void EXTI15_10_IRQHandler(void)
{
	if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) 
	{		
		LED2_TOGGLE;
		EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);     
	}  
}
  • 7
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32中,外部中断的初始化可以通过以下步骤完成: 1. 配置外部中断线:根据需要选择外部中断线,例如EXTI_Line4。\[2\] 2. 初始化EXTI_InitTypeDef结构体:定义一个EXTI_InitTypeDef结构体,并设置其成员变量,包括EXTI_Line(指定中断线)、EXTI_Mode(指定是事件还是中断)、EXTI_Trigger(指定触发方式)和EXTI_LineCmd(是否使能)。\[2\] 3. 调用EXTI_Init函数:将初始化好的EXTI_InitTypeDef结构体作为参数传入EXTI_Init函数,以初始化外设EXTI寄存器。\[2\] 以下是一个外部中断初始化的示例代码: ```c EXTI_InitTypeDef EXTI_InitStructure; EXTI_InitStructure.EXTI_Line = EXTI_Line4; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); ``` 在上述代码中,我们选择了EXTI_Line4作为外部中断线,并设置了中断模式为中断,触发方式为下降沿触发,使能外部中断。通过调用EXTI_Init函数,将配置好的EXTI_InitStructure结构体传入,即可完成外部中断的初始化。\[2\] #### 引用[.reference_title] - *1* *3* [stm32外部中断](https://blog.csdn.net/qq_62846920/article/details/124655894)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [stm32学习笔记——外部中断](https://blog.csdn.net/Zn_Hua/article/details/120780463)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值