21 votos

Evento Stm32 e interrupciones

Comencé a estudiar las interrupciones en stm32 específicamente el tablero de descubrimiento stm32f4. Encontré este ejemplo en el que hay que pulsar el botón para iniciar la interrupción y volver a pulsarlo para detenerla.

En esta línea:EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt tenemos que elegir el modo de interrupción o el modo de evento. Lo cambié a modo de evento pero parece que no funciona, así que llegué a la conclusión de que el handler se ejecuta sólo con interrupciones.

¿Por qué usamos Eventos en stm32 si no puedes ejecutar algún código cuando sucede?

Aquí está el código:

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

18voto

xilun Puntos 261

A veces, encontrar la respuesta a estas preguntas para un dispositivo ARM puede ser más difícil que con los microcontroladores más simples, porque la información suele estar repartida en guías familiares y de programación en lugar de estar incluida en la hoja de datos. En este caso la respuesta parece estar en la página 377 del RM0090 Manual de referencia :

Los STM32F4xx son capaces de manejar eventos externos o internos para despertar el núcleo (WFE). El evento del despertar puede ser generado por:

  • (He eliminado los detalles del modo de interrupción externa normal)

  • o configurando una línea EXTI externa o interna en el modo de eventos. Cuando la CPU se reanuda de WFE, no es necesario limpiar la interrupción periférica pendiente de bit o el NVIC Canal IRQ bit pendiente, ya que el bit pendiente correspondiente a la línea de eventos no está fijado.

Por lo tanto, parece que el propósito principal es permitir los despertares sin generar una interrupción o tener que responder a las interrupciones durante el funcionamiento normal.

No se menciona en esa guía y no estoy seguro de cuán aplicable es a la arquitectura del STM32, pero en algunos otros dispositivos los esquemas similares pueden ser útiles para captar eventos rápidos sin generar una interrupción. Por ejemplo, puede tener una aplicación en la que es importante capturar que un evento de sub-microsegundo ha ocurrido, pero no hay necesidad de responder a él rápidamente, así que sólo puede comprobar una bandera para ver si ha ocurrido.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X