Stm32 Событие и прерывания

17

Я начал изучать прерывания на 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)
            {
            }
        }
ChiPlusPlus
источник

Ответы:

14

Иногда найти ответ на эти вопросы для устройства ARM может быть сложнее, чем для простых микроконтроллеров, поскольку информация часто распространяется по семействам и руководствам по программированию, а не включается в таблицу данных. В этом случае ответ представляется на стр. 381 Справочного руководства RM0090 :

STM32F4xx способен обрабатывать внешние или внутренние события, чтобы пробудить ядро ​​(WFE). Событие пробуждения может быть сгенерировано:

  • (Я удалил обычные детали режима внешнего прерывания)

  • или настройка внешней или внутренней линии EXTI в режиме событий. Когда процессор возобновляет работу из WFE, нет необходимости очищать бит ожидания периферийного прерывания или бит ожидания NVIC IRQ, поскольку бит ожидания, соответствующий строке события, не установлен.

Таким образом, похоже, что основная цель состоит в том, чтобы включить пробуждения без создания прерывания или необходимости реагировать на прерывания во время нормальной работы.

Это не упоминается в этом руководстве, и я не уверен, насколько это применимо к архитектуре STM32, но на некоторых других устройствах подобные схемы могут быть полезны для перехвата быстрых событий без генерации прерывания. Например, у вас может быть приложение, в котором важно фиксировать, что произошло событие с микросекундами, но нет необходимости быстро на него реагировать, поэтому вы можете просто проверить флаг, чтобы увидеть, произошло ли оно.

Изменить: (5/2018) На сегодняшний день номер страницы ссылочного текста является страница 381 (ранее страница 377)

PeterJ
источник
1
Да, на PIC кажется, что большая часть того, что я делаю в прерывании, это установка флагов. В Cortex большинство этих флагов устанавливаются без прерывания, поэтому я использую меньше прерываний
Скотт Сейдман,