Stm32 事件和中断

电器工程 stm32 中断 stm32f4
2022-01-21 17:55:22

我开始研究 stm32 上的中断,特别是 stm32f4 发现板。我发现了这个例子,你必须按下按钮来启动中断并再次按下它来停止它。

在这一行:EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt 我们必须选择中断模式或事件模式。我将它更改为事件模式,但它似乎不起作用。所以我得出的结论是,处理程序仅在中断的情况下执行。

如果某些代码发生时无法执行,为什么我们还要在 stm32 上使用事件?

这是代码:

        #include "stm32f4xx.h"
        #include "stm32f4xx_syscfg.h"
        #include "stm32f4xx_rcc.h"
        #include "stm32f4xx_gpio.h"
        #include "stm32f4xx_exti.h"
        #include "misc.h"



        EXTI_InitTypeDef   EXTI_InitStructure;

        void EXTILine0_Config(void);
        void LEDInit(void);


        void ExtInt(void)
        {

          LEDInit();

          /* Configure EXTI Line0 (connected to PA0 pin) in interrupt mode */
          EXTILine0_Config();

          /* Generate software interrupt: simulate a rising edge applied on EXTI0 line */
          EXTI_GenerateSWInterrupt(EXTI_Line0);

          while (1)
          {
          }
        }

        /**
          * @brief  Configures LED GPIO.
          * @param  None
          * @retval None
          */
        void LEDInit()
        {
          GPIO_InitTypeDef  GPIO_InitStructure;

          /* Enable the GPIO_LED Clock */
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

          /* Configure the GPIO_LED pin */
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
          GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
          GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_Init(GPIOD, &GPIO_InitStructure);
        }

        /**
          * @brief  Configures EXTI Line0 (connected to PA0 pin) in interrupt mode
          * @param  None
          * @retval None
          */
        void EXTILine0_Config(void)
        {

          GPIO_InitTypeDef   GPIO_InitStructure;
          NVIC_InitTypeDef   NVIC_InitStructure;

          /* Enable GPIOA clock */
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
          /* Enable SYSCFG clock */
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

          /* Configure PA0 pin as input floating */
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
          GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
          GPIO_Init(GPIOA, &GPIO_InitStructure);

          /* Connect EXTI Line0 to PA0 pin */
          SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

          /* Configure EXTI Line0 */
          EXTI_InitStructure.EXTI_Line = EXTI_Line0;
          EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
          EXTI_InitStructure.EXTI_LineCmd = ENABLE;
          EXTI_Init(&EXTI_InitStructure);

          /* Enable and set EXTI Line0 Interrupt to the lowest priority */
          NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);
        }

        /**
          * @brief  This function handles External line 0 interrupt request.
          * @param  None
          * @retval None
          */
        void EXTI0_IRQHandler(void)
        {
          if(EXTI_GetITStatus(EXTI_Line0) != RESET)
          {
            /* Toggle LED1 */
            GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

            /* Clear the EXTI line 0 pending bit */
            EXTI_ClearITPendingBit(EXTI_Line0);
          }
        }

        /**
          * @}
          */

        /**
          * @}
          */

        /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

        int main(void)
        {

            while(1)
            {
            }
        }
2个回答

有时,为 ARM 设备找到这些问题的答案可能比更简单的微控制器更困难,因为这些信息通常分布在系列和编程指南中,而不是包含在数据表中。在这种情况下,答案似乎在RM0090 参考手册的第 381 页:

STM32F4xx 能够处理外部或内部事件以唤醒内核 (WFE)。唤醒事件可以通过以下方式生成:

  • (我已经删除了正常的外部中断模式细节)

  • 或在事件模式下配置外部或内部 EXTI 线。当 CPU 从 WFE 恢复时,不需要清除外设中断挂起位或 NVIC IRQ 通道挂起位,因为未设置事件线对应的挂起位。

因此,主要目的似乎是在正常操作期间启用唤醒而不产生中断或不必响应中断。

该指南中没有提到它,我不确定它如何适用于 STM32 架构,但在其他一些设备上,类似的方案对于捕获快速事件而不产生中断很有用。例如,您可能有一个应用程序,在该应用程序中捕获发生的亚微秒事件很重要,但不需要快速响应它,因此您只需检查一个标志以查看它是否发生。

编辑:(5/2018)截至今天,参考文本的页码为第 381 页(以前为第 377 页)

如果某些代码发生时无法执行,为什么我们还要在 stm32 上使用事件?

中断通常用于由 ARM 内核(NVIC、中断处理程序等)执行几行代码。

事件不需要执行代码,但可以通知另一个外围设备在没有处理器干预的情况下执行某些操作。例如,周期性定时器可以生成一个事件来告诉 ADC 进行采样,然后使用 DMA 将测量值写入内存,而无需唤醒 ARM 核心处理器(理论上不执行任何代码)。

所以中断涉及代码执行。事件不一定需要代码执行。