简体   繁体   English

如果多个引脚共享同一个中断,我如何知道哪个引脚触发了中断?

[英]How do I know which pin is triggering the interrupt if multiple pins share the same interrupt?

I am writing code with the STM323 ide and using the STM32f303re nucleo board.我正在使用 STM323 ide 编写代码并使用 STM32f303re 核板。 I configured pin PA7 as an interrupt, however it does not have its own interrupt handler like previous development boards i've worked with.我将引脚 PA7 配置为中断,但是它没有像我以前使用过的开发板那样拥有自己的中断处理程序。

在此处输入图像描述

As you can see, this one interrupt handler handles interrupts from pins 9-5, thus if any of these pins are triggered they will call the same interrupt.如您所见,这个中断处理程序处理来自引脚 9-5 的中断,因此如果这些引脚中的任何一个被触发,它们将调用相同的中断。 I need to be able to perform different functions depending on which pin is triggered.我需要能够根据触发的引脚执行不同的功能。 Is there a way to know which specific pin was causing the interrupt?有没有办法知道哪个特定引脚导致中断?

You can use EXTI_GetITStatus , to check which line causing interrupt.您可以使用EXTI_GetITStatus来检查导致中断的行。

 /* Handle PA7 interrupt */
void EXTI9_5_IRQHandler(void) {
    /* Make sure that interrupt flag is set */
    if (EXTI_GetITStatus(EXTI_Line7) != RESET) {
        /* Do your stuff when PA7 is changed */
        
        
        /* Clear interrupt flag */
        EXTI_ClearITPendingBit(EXTI_Line7);
    }
}

Do not forget to clear flag after.之后不要忘记清除标志。

For the cases when multiple pins share an interrupt, when the interrupt fires, you need to check what pin specifically caused an interrupt.对于多个引脚共享一个中断的情况,当中断触发时,您需要检查具体是哪个引脚引起了中断。 Unlike pin 1 interrupt, where the interrupt itself means it was pin 1 and you can process it right away, in this case an interrupt means "it's either pin 5, or 6, or 7, or 8, or 9", so in the ISR you need to check "was it pin 5? or 6?..."与引脚 1 中断不同,中断本身意味着它是引脚 1,您可以立即处理它,在这种情况下,中断意味着“它是引脚 5、或 6、或 7、或 8 或 9”,所以在ISR 您需要检查“是引脚 5?还是 6?...”

I think it's a good opportunity to look directly into the registers of EXTI peripheral.我认为这是一个直接查看 EXTI 外设寄存器的好机会。

If you open the reference manual of your MCU on page 299, section 14.3.6, you can see this EXTI_PR1 register holds pending bits for lines 0..31.如果您打开第 299 页第 14.3.6 节的 MCU 参考手册,您可以看到这个 EXTI_PR1 寄存器保存第 0..31 行的未决位。 Those bits are marked as rc_w1, which from the start of the document means (reference manual, page 46):这些位被标记为 rc_w1,从文档开始就意味着(参考手册,第 46 页):

read/clear (rc_w1)读取/清除 (rc_w1)

Software can read as well as clear this bit by writing 1. Writing '0' has no effect on the bit value.软件可以通过写入 1 来读取和清除该位。写入“0”对位值没有影响。

So the logic is the following: if an interrupt of lines 5..9 occurred, you need to check what bit specifically in that register is set to 1, and then you write 1 there to reset it.所以逻辑如下:如果发生第 5..9 行的中断,您需要检查该寄存器中具体的哪个位设置为 1,然后在此处写入 1 以将其复位。 This will clear the flag.这将清除标志。

void EXTI9_5_IRQHandler(void)
{
 if(EXTI_PR1 & (1U<<5U)) //check if it's line 5, returns 0 if PR5 is 0, otherwise returns non-zero, which is true
 {
   EXTI_PR1 |= (1U<<5U); //write 1 to that bit to clear it so interrupt doesn't fire again once ISR is finished
   do_stuff_if_it's_pin5();
 }

}

Alternatively, instead of 1U<<5U you should be able to use EXTI_PR1_PR5, so the code would look a little easier to read, like this:或者,您应该能够使用 EXTI_PR1_PR5 而不是 1U<<5U,这样代码看起来更容易阅读,如下所示:

void EXTI9_5_IRQHandler(void)
    {
     if(EXTI_PR1 & EXTI_PR1_PR5) //check if it's line 5, returns 0 if PR5 is 0, otherwise returns non-zero, which is true
     {
       EXTI_PR1 |= EXTI_PR1_PR5; //write 1 to that bit to clear it so interrupt doesn't fire again once ISR is finished
       do_stuff_if_it's_pin5();
     }
    
    }

This is what the functions provided by @Lime7 do behind the scenes, I suspect (can't check, but it makes logical sense).这是@Lime7 提供的功能在幕后所做的,我怀疑(无法检查,但合乎逻辑)。

I don't have that microcontroller to test it, but it should work.我没有那个微控制器来测试它,但它应该可以工作。

Other answers already covered the interrupt flags.其他答案已经涵盖了中断标志。 I'm going to add some info regarding CubeMX and HAL, since it looks like you are using them.我将添加一些有关 CubeMX 和 HAL 的信息,因为看起来您正在使用它们。

When you enable a GPIO interrupt in CubeMX, the code generator adds a line in the appropriate IRQ handler function.当您在 CubeMX 中启用 GPIO 中断时,代码生成器会在相应的 IRQ 处理函数中添加一行。 When multiple interrupts are enabled, the generated code looks like so (comments removed):当启用多个中断时,生成的代码如下所示(注释已删除):

void EXTI9_5_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
}

The HAL_GPIO_EXTI_IRQHandler() function checks the interrupt status for the given pin and calls HAL_GPIO_EXTI_Callback() function if the flag is set. HAL_GPIO_EXTI_IRQHandler()函数检查给定引脚的中断状态,如果设置了标志,则调用HAL_GPIO_EXTI_Callback()函数。

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

In the HAL flow, you don't typically write code directly in the IRQ handler, but implement the HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) function.在 HAL 流程中,您通常不会直接在 IRQ 处理程序中编写代码,而是实现HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)函数。 The pin that triggered the interrupt is provided as a parameter for your convenience.为方便起见,将触发中断的引脚作为参数提供。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM