STM32外部中断

stm32G431总共有111个中断源,所以有时难免有两个或者两个以上的中断一起来临,或者正在处理一个中断服务函数时突然又有一个中断来临,所以微控制器都有一个处理中断的机制。stm32系列芯片用到的机制是:NVIC

NVIC:嵌套向量中断控制器(Nested Vectored Interrupt Controller),STM32的中有一个强大而方便的NVIC,它是属于CM4内核的器件。NVIC 控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对CM4内核里面的NVIC进行裁剪,把不需要的部分去掉,所以STM32的NVIC是CM4的NVIC的一个子集

NVIC寄存器定义在core_cm4.h文件中,CM4内核支持256个中断,其中包含了16个系统异常和240个外部中断,并且具有256级的可编程中断设置。但 STM32并没有使用CM4内核的全部东西,而是只用了它的一部分,stm32G431芯片有111个中断,包括9个内核中断和102个可屏蔽中断,具有16级可编程的中断优先级,我们常用的就是这102个可屏蔽中断。

NVIC中断系统

 

 

Cortex-M4优先级设定

 

  • 支持3个固定的高优先级和多达256级的可编程优先级,支持128级抢占。
  • 每个中断的优先级由一个8位的寄存器来设定,分为高低两个位段。高位段表示抢占优先级,低位段表示响应(子)优先级。 CM4允许最少使用位数为3个位,即至少要支持8级优先级。
  • 优先级以MSB对齐,简化程序的跨器件移植

STM32中有两个优先级的概念:抢占式优先级  和  响应优先级(子优先级),每个中断源都需要被指定这两种优先级。

  • 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套在低抢占式优先级的中断中。
  • 当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理
  • 如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个。
  • 如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断向量表中的排位顺序决定先处理哪一个。

EXTI外部中断/时间控制器

STM32G431每个引脚都可以设置为外部线中断输入,实际上,stm32芯片集成了一个外部中断/事件控制器(EXTI),由23个能产生事件/中断请求的边沿检测器组成,每个输入线可以独立地配置输入类型(事件或中断)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。 

23个中断/事件请求包括:

  • IO可以做为EXTI线(0..15)【常用
  • 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 唤醒事件
  • 使用外部线中断需要开启AFIO中对应的中断功能。 

然后我们常用的是I/O作为外部中断输入,每个引脚都可以设为外部线中断输入。

然后就看看程序代码了

中断向量地址,startup_stm32g431xx.s文件和手册中的对比一下,也就可以发现是差不多了。

NVIC的相关函数 

  • 设置中断优先级组

一般是nvic_prioritygroup2,所以以后要配置,即2位抢占式优先级  和2位响应优先级

再看看设置中断优先级组底层函数

  • 设置中断优先级组

/**
  * @brief  Set the priority grouping field (pre-emption priority and subpriority)
  *         using the required unlock sequence.
  * @param  PriorityGroup: The priority grouping bits length.
  *         This parameter can be one of the following values:
  *         @arg NVIC_PRIORITYGROUP_0: 0 bit  for pre-emption priority,
  *                                    4 bits for subpriority
  *         @arg NVIC_PRIORITYGROUP_1: 1 bit  for pre-emption priority,
  *                                    3 bits for subpriority
  *         @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
  *                                    2 bits for subpriority
  *         @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
  *                                    1 bit  for subpriority
  *         @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
  *                                    0 bit  for subpriority
  * @note   When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
  *         The pending IRQ priority will be managed only by the subpriority.
  * @retval None
  */
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));

  /* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
  NVIC_SetPriorityGrouping(PriorityGroup);
}
  • 设置中断优先级 

 

/**
  * @brief  Set the priority of an interrupt.
  * @param  IRQn: External interrupt number.
  *         This parameter can be an enumerator of IRQn_Type enumeration
  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32g4xxxx.h))
  * @param  PreemptPriority: The pre-emption priority for the IRQn channel.
  *         This parameter can be a value between 0 and 15
  *         A lower priority value indicates a higher priority
  * @param  SubPriority: the subpriority level for the IRQ channel.
  *         This parameter can be a value between 0 and 15
  *         A lower priority value indicates a higher priority.
  * @retval None
  */
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
{
  uint32_t prioritygroup;

  /* Check the parameters */
  assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));

  prioritygroup = NVIC_GetPriorityGrouping();

  NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
}

HAL_NVIC_SetPriority函数用于设置一个中断的优先级,它有三个形参,第一个为IRQn_Type类型参数,指定中断源。 第二个和第三个形参分别设定中断的抢占式优先级和响应优先级,这个的设置要与中断组配合使用。

HAL_NVIC_SetPriority函数实际是调用定义在core_cm4.h文件的NVIC_SetPriority函数实现功能的,该函数通过设置SCB_SHP寄存器或者NVIC_IPRx寄存器实现功能。

  • 使能中断

按住ctrl+f,可以查找一下

 

/**
  * @brief  Enable a device specific interrupt in the NVIC interrupt controller.
  * @note   To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
  *         function should be called before.
  * @param  IRQn External interrupt number.
  *         This parameter can be an enumerator of IRQn_Type enumeration
  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32g4xxxx.h))
  * @retval None
  */
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
{
  /* Check the parameters */
  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
  
  /* Enable interrupt */
  NVIC_EnableIRQ(IRQn);
}

HAL_NVIC_EnableIRQ函数用于在NVIC控制器中使能指定中断,它有一个形参,是IRQn_Type类型参数。 HAL_NVIC_EnableIRQ函数实际是通过调用定义在core_cm4.h文件中NVIC_EnableIRQ函数实现功能,NVIC_EnableIRQ函数设置了NVIC_ISER寄存器内容。

  • 不允许中断

 

/**
  * @brief  Disable a device specific interrupt in the NVIC interrupt controller.
  * @param  IRQn External interrupt number.
  *         This parameter can be an enumerator of IRQn_Type enumeration
  *         (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32g4xxxx.h))
  * @retval None
  */
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
{
  /* Check the parameters */
  assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
  
  /* Disable interrupt */
  NVIC_DisableIRQ(IRQn);
}

HAL_NVIC_DisableIRQ函数是在NVIC控制器中禁用指定中断,用法与HAL_NVIC_EnableIRQ函数相同。最终通过设置NVIC_ICER寄存器值实现功能 

  • NVIC中断系统函数

/**
  * @brief  Initiate a system reset request to reset the MCU.
  * @retval None
  */
void HAL_NVIC_SystemReset(void)
{
  /* System Reset */
  NVIC_SystemReset();
}

HAL_NVIC_SystemReset函数用于初始化一个MCU复位要求,它设计调用NVIC_SystemReset函数实现功能。

了解了这些应该就可以写代码了(这里我们用按键来作为外部中断的触发条件) 

所以B1和B4只能选一个来作为外部中断触发条件。

首先配置stm32cubemx

这里配置触发模式

使能中断

设置两位抢占式优先级(但我感觉这里不配置也行。。。)

然后在keil里面找到虚函数,重写虚函数。

和中断相关的函数一般在这个.c文件里

然后往里去找

 

 

找到之后在main函数中重写

main.c

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_0)  // B4
	{
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_8);
	}
	if(GPIO_Pin == GPIO_PIN_1)  //B2
	{
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_9);
	}
	if(GPIO_Pin == GPIO_PIN_2)  //B3
	{
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_10);
	}
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
	HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
/* USER CODE END 0 */

个人拙见:去keil里多看看一些中断相关的函数,看着看着就顺眼了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
外部中断是指由外部信号触发的中断事件。在STM32微控制器中,外部中断可以通过引脚的外部触发方式来实现。以下是一些关于STM32外部中断的常见问题和回答: 1. 如何配置外部中断? 首先,选择要作为外部中断触发源的引脚。然后,使用GPIO库函数将引脚配置为输入模式,并启用外部中断功能。最后,配置外部中断触发条件,例如上升沿、下降沿或双边沿触发。具体的配置步骤和函数可以参考ST固件库或者HAL库的文档。 2. 如何编写外部中断的中断服务函数? 在STM32微控制器上,外部中断触发时,会跳转到预定义的中断服务函数。您需要在代码中编写该中断服务函数,并根据需求进行处理。可以使用HAL库提供的函数来判断是哪个引脚触发了中断,并进行相应的处理。 3. 外部中断有哪些触发方式? STM32微控制器支持多种触发方式,包括上升沿触发(Rising Edge Trigger)、下降沿触发(Falling Edge Trigger)、双边沿触发(Rising/Falling Edge Trigger)等。您可以根据实际需求选择合适的触发方式。 4. 外部中断能同时处理多个引脚的中断吗? 是的,STM32微控制器支持同时处理多个引脚的外部中断。您可以配置多个引脚为外部中断触发源,并在中断服务函数中根据需要进行处理。 请注意,以上回答是基于一般情况下的使用,具体的配置和编程方式可能会因不同的STM32系列、芯片型号和开发环境而有所差异。建议您参考相关的文档和例程来进行具体的配置和编程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wu小燕呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值