Événement Stm32 et interruptions

17

J'ai commencé à étudier les interruptions sur stm32, en particulier la carte de découverte stm32f4. j'ai trouvé cet exemple dans lequel vous devez appuyer sur le bouton pour démarrer l'interruption et le pousser à nouveau pour l'arrêter.

Dans cette ligne: EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt, nous devons choisir le mode d'interruption ou le mode d'événement. Je l'ai changé en mode événement mais cela ne semble pas fonctionner. Je suis donc sorti avec la conclusion que le gestionnaire est exécuté avec des interruptions uniquement.

Pourquoi utilisons-nous ensuite des événements sur stm32 si vous ne pouvez pas exécuter du code quand ils se produisent?

Voici le 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
la source

Réponses:

14

Parfois, trouver la réponse à ces questions pour un périphérique ARM peut être plus difficile que des microcontrôleurs plus simples car les informations sont souvent réparties entre les guides de famille et de programmation plutôt que incluses dans la fiche technique. Dans ce cas, la réponse semble être à la page 381 du manuel de référence RM0090 :

Les STM32F4xx sont capables de gérer des événements externes ou internes afin de réveiller le cœur (WFE). L'événement de réveil peut être généré soit par:

  • (J'ai supprimé les détails du mode d'interruption externe normal)

  • ou configurer une ligne EXTI externe ou interne en mode événement. Lorsque le CPU reprend à partir de WFE, il n'est pas nécessaire d'effacer le bit en attente d'interruption périphérique ou le bit en attente du canal NVIC IRQ car le bit en attente correspondant à la ligne d'événement n'est pas défini.

Il semble donc que l'objectif principal est de permettre des réveils sans générer d'interruption ni avoir à répondre à des interruptions pendant le fonctionnement normal.

Il n'est pas mentionné dans ce guide et je ne sais pas dans quelle mesure il est applicable à l'architecture STM32 mais sur certains autres appareils, des schémas similaires peuvent être utiles pour capturer des événements rapides sans générer d'interruption. Par exemple, vous pouvez avoir une application où il est important de capturer qu'un événement inférieur à la microseconde s'est produit, mais il n'est pas nécessaire d'y répondre rapidement, vous pouvez donc simplement vérifier un indicateur pour voir s'il s'est produit.

Edit: (5/2018) À ce jour, le numéro de page du texte référencé est la page 381 (anciennement la page 377)

PeterJ
la source
1
Oui, sur les PIC, il semble qu'une grande partie de ce que je fais dans une interruption consiste à définir des indicateurs. Dans Cortex, la plupart de ces indicateurs sont définis sans avoir à interrompre, donc j'utilise moins d'interruptions
Scott Seidman