Stm32-Ereignis und Interrupts

17

Ich habe begonnen, Interrupts auf stm32 zu studieren, insbesondere auf dem stm32f4-Discovery-Board. Ich habe dieses Beispiel gefunden, in dem Sie die Taste drücken müssen, um den Interrupt zu starten, und erneut drücken müssen, um ihn zu stoppen.

In dieser Zeile: EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt müssen wir entweder den Interrupt-Modus oder den Event-Modus wählen. Ich habe es in den Event-Modus geändert, aber es scheint nicht zu funktionieren. Also kam ich zu dem Schluss, dass der Handler nur mit Interrupts ausgeführt wird.

Warum verwenden wir dann Events auf stm32, wenn Sie in diesem Fall keinen Code ausführen können?

Hier ist der Code:

        #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)
            {
            }
        }
ChiPlusPlus
quelle

Antworten:

14

Manchmal kann es schwieriger sein, die Antwort auf diese Fragen für ein ARM-Gerät zu finden als für einfachere Mikrocontroller, da die Informationen häufig über Familien- und Programmierhandbücher verteilt und nicht im Datenblatt enthalten sind. In diesem Fall befindet sich die Antwort auf Seite 381 des RM0090-Referenzhandbuchs :

Der STM32F4xx kann externe oder interne Ereignisse verarbeiten, um den Core (WFE) aufzuwecken. Das Aufweckereignis kann folgendermaßen generiert werden:

  • (Ich habe normale externe Interrupt-Modus Details entfernt)

  • oder Konfigurieren einer externen oder internen EXTI-Leitung im Ereignismodus. Wenn die CPU von der WFE zurückkehrt, ist es nicht erforderlich, das anstehende Bit des Peripherie-Interrupts oder das anstehende Bit des NVIC-IRQ-Kanals zu löschen, da das anstehende Bit, das der Ereignisleitung entspricht, nicht gesetzt ist.

Es scheint also der Hauptzweck zu sein, das Aufwecken zu ermöglichen, ohne dass während des normalen Betriebs ein Interrupt generiert oder auf Interrupts reagiert werden muss.

Es wird in diesem Handbuch nicht erwähnt, und ich bin mir nicht sicher, ob es für die STM32-Architektur geeignet ist, aber auf einigen anderen Geräten können ähnliche Schemata hilfreich sein, um schnelle Ereignisse abzufangen, ohne einen Interrupt zu generieren. Beispielsweise haben Sie möglicherweise eine Anwendung, in der es wichtig ist, das Auftreten eines Ereignisses im Sub-Mikrosekunden-Bereich zu erfassen. Sie müssen jedoch nicht schnell darauf reagieren, sodass Sie einfach ein Flag überprüfen können, um festzustellen, ob es aufgetreten ist.

Edit: (5/2018) Seit heute ist die Seitenzahl des referenzierten Texts Seite 381 (früher Seite 377).

PeterJ
quelle
1
Ja, auf PICs scheint es, dass vieles, was ich in einem Interrupt mache, gesetzte Flags sind. In Cortex werden die meisten dieser Flags gesetzt, ohne unterbrochen zu werden, sodass ich weniger Interrupts verwende
Scott Seidman,