Stm32 Zdarzenie i przerwania

17

Zacząłem studiować przerwania na stm32, a konkretnie na płycie odkrywania stm32f4. znalazłem ten przykład, w którym musisz nacisnąć przycisk, aby rozpocząć przerwanie i nacisnąć go ponownie, aby go zatrzymać.

W tym wierszu: EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt musimy wybrać tryb przerwania lub tryb zdarzenia. Zmieniłem go na tryb zdarzeń, ale wydaje się, że to nie działa. Więc doszedłem do wniosku, że program obsługi jest wykonywany tylko z przerwami.

Dlaczego używamy Zdarzenia na STM32, jeśli nie możesz wykonać kodu, gdy się zdarzy?

Oto kod:

        #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
źródło

Odpowiedzi:

14

Czasami znalezienie odpowiedzi na te pytania dla urządzenia ARM może być trudniejsze niż prostsze mikrokontrolery, ponieważ informacje są często rozproszone w rodzinie i przewodnikach programowych, a nie zawarte w arkuszu danych. W tym przypadku wydaje się, że odpowiedź znajduje się na stronie 381 instrukcji RM0090 Reference :

STM32F4xx są w stanie obsługiwać zdarzenia zewnętrzne lub wewnętrzne w celu wybudzenia rdzenia (WFE). Zdarzenie budzenia można wygenerować:

  • (Usunąłem szczegóły normalnego trybu zewnętrznego przerwania)

  • lub konfigurowanie zewnętrznej lub wewnętrznej linii EXTI w trybie zdarzenia. Gdy procesor wznawia pracę z WFE, nie jest konieczne usuwanie oczekującego bitu przerwań peryferyjnych lub bitu oczekującego kanału IRIC NVIC, ponieważ bit oczekujący odpowiadający linii zdarzenia nie jest ustawiony.

Wydaje się więc, że głównym celem jest umożliwienie wybudzania bez generowania przerwania lub konieczności reagowania na przerwania podczas normalnej pracy.

W tym przewodniku nie wspomniano o tym i nie jestem pewien, jak ma zastosowanie do architektury STM32, ale na niektórych innych urządzeniach podobne schematy mogą być przydatne do przechwytywania szybkich zdarzeń bez generowania przerwania. Na przykład możesz mieć aplikację, w której ważne jest, aby uchwycić, że wystąpiło zdarzenie poniżej mikrosekundy, ale nie ma potrzeby szybkiego reagowania na to, więc możesz po prostu sprawdzić flagę, aby zobaczyć, czy wystąpiło.

Edycja: (5/2018) Na dzień dzisiejszy numer strony przywoływanego tekstu to strona 381 (poprzednio strona 377)

PeterJ
źródło
1
Tak, na PIC wydaje się, że znaczną część tego, co robię w przerwie, stanowią flagi. W Corteksie większość z tych flag jest ustawiana bez konieczności przerywania, dlatego używam mniej przerwań
Scott Seidman,