MDK环境 GPIO输入中断分析

 通过GPIO终端输入例程来学习了中断配置。    例程例程:按键K3触发中断,进入中断后,通过串口打印出按键信息。
    一、硬件电路:
         <ignore_js_op>
         <ignore_js_op>
        K3按键进入RT1052的L6引脚,对应的端口是GPIO5_IO00。
         <ignore_js_op>
    二、程序:
        2.1、主程序:
        int main(void)
        {
            gpio_pin_config_t sw_config = {
            kGPIO_DigitalInput, 0,     //端口设置为输入
            kGPIO_IntRisingEdge,      //端口设置为上升沿中断           
            };

        BOARD_ConfigMPU();
        BOARD_InitPins();        //初始化引脚
        BOARD_BootClockRUN();
        BOARD_InitDebugConsole();
        PRINTF("GPIO Driver example.\r\n");


        EnableIRQ(EXAMPLE_SW_IRQ);     //使能中断
        GPIO_PinInit(EXAMPLE_SW_GPIO, EXAMPLE_SW_GPIO_PIN, &sw_config);   //初始化GPIO5_IO00引脚
        GPIO_PortEnableInterrupts(EXAMPLE_SW_GPIO, 1U << EXAMPLE_SW_GPIO_PIN);

        while(1)
       {
            if(g_InputSignal)
            {
                delay();
                if(1 == GPIO_PinRead(EXAMPLE_SW_GPIO, EXAMPLE_SW_GPIO_PIN))
                {
                    PRINTF("%s is turned on.\r\n", EXAMPLE_SW_NAME);
                }
                g_InputSignal = false;
            }
        }
    }
        //中断程序
        void EXAMPLE_GPIO_IRQHandler(void)
        {
             GPIO_PortClearInterruptFlags(EXAMPLE_SW_GPIO, 1U << EXAMPLE_SW_GPIO_PIN);
             g_InputSignal = true;
             exception return operation might vector to incorrect interrupt */
             #if defined __CORTEX_M && (__CORTEX_M == 4U)
                 __DSB();
             #endif
         }
    2.2、对上面红色字体的函数进行分析
        2.2.1、 BOARD_InitPins();        //初始化引脚
这个函数在 pin_mux.c中定义
       void BOARD_InitPins(void)
        {
            CLOCK_EnableClock(kCLOCK_Iomuxc);           
            CLOCK_EnableClock(kCLOCK_IomuxcSnvs);   

        IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_12_LPUART1_TX, 0U);        //复用GPIO引脚设置为串口1   
            IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_13_LPUART1_RX,  0U);               
            IOMUXC_SetPinMux(IOMUXC_SNVS_WAKEUP_GPIO5_IO00, 0U);           //GPIO5_IO00配置为输入
            IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_12_LPUART1_TX, 0x10B0u);                              
            IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX, 0x10B0u);                             
        }
        2.2.2、 EnableIRQ(EXAMPLE_SW_IRQ);     //使能中断
               这个函数在fsl_common.h中定义
            static inline status_t EnableIRQ(IRQn_Type interrupt)
            {
                if (NotAvail_IRQn == interrupt)
                {
                    return kStatus_Fail;
}
                    NVIC_EnableIRQ(interrupt);
                 return kStatus_Success;
            }

            IRQn_Type结构中有关GPIO口的定义:
            typedef enum IRQn {
              /* Auxiliary constants */
              NotAvail_IRQn                = -128,             /**< Not available device specific interrupt */


              GPIO1_INT0_IRQn              = 72,               /**< Active HIGH Interrupt from INT0 from GPIO */
              GPIO1_INT1_IRQn              = 73,               /**< Active HIGH Interrupt from INT1 from GPIO */
              GPIO1_INT2_IRQn              = 74,               /**< Active HIGH Interrupt from INT2 from GPIO */
              GPIO1_INT3_IRQn              = 75,               /**< Active HIGH Interrupt from INT3 from GPIO */
              GPIO1_INT4_IRQn              = 76,               /**< Active HIGH Interrupt from INT4 from GPIO */
              GPIO1_INT5_IRQn              = 77,               /**< Active HIGH Interrupt from INT5 from GPIO */
              GPIO1_INT6_IRQn              = 78,               /**< Active HIGH Interrupt from INT6 from GPIO */
              GPIO1_INT7_IRQn              = 79,               /**< Active HIGH Interrupt from INT7 from GPIO */
              GPIO1_Combined_0_15_IRQn     = 80,               /**< Combined interrupt indication for GPIO1 signal 0 throughout 15 */
              GPIO1_Combined_16_31_IRQn    = 81,               /**< Combined interrupt indication for GPIO1 signal 16 throughout 31 */
              GPIO2_Combined_0_15_IRQn     = 82,               /**< Combined interrupt indication for GPIO2 signal 0 throughout 15 */
              GPIO2_Combined_16_31_IRQn    = 83,               /**< Combined interrupt indication for GPIO2 signal 16 throughout 31 */
              GPIO3_Combined_0_15_IRQn     = 84,               /**< Combined interrupt indication for GPIO3 signal 0 throughout 15 */
              GPIO3_Combined_16_31_IRQn    = 85,               /**< Combined interrupt indication for GPIO3 signal 16 throughout 31 */
              GPIO4_Combined_0_15_IRQn     = 86,               /**< Combined interrupt indication for GPIO4 signal 0 throughout 15 */
              GPIO4_Combined_16_31_IRQn    = 87,               /**< Combined interrupt indication for GPIO4 signal 16 throughout 31 */
              GPIO5_Combined_0_15_IRQn     = 88,               /**< Combined interrupt indication for GPIO5 signal 0 throughout 15 */
              GPIO5_Combined_16_31_IRQn    = 89,               /**< Combined interrupt indication for GPIO5 signal 16 throughout 31 */

           } IRQn_Type;
        >中断使能参数定义:
#define EXAMPLE_SW_IRQ BOARD_USER_BUTTON_IRQ
          #define BOARD_USER_BUTTON_IRQ GPIO5_Combined_0_15_IRQn
          调用EnableIRQ(EXAMPLE_SW_IRQ);     函数的参数就是上面定义的中断号为88


            NVIC_EnableIRQ(interrupt);函数定义:
            #define NVIC_EnableIRQ              __NVIC_EnableIRQ
__NVIC_EnableIRQ函数定义:

/**
              \brief   Enable Interrupt
              \details Enables a device specific interrupt in the NVIC interrupt controller.
              \param [in]      IRQn  Device specific interrupt number.
              \note    IRQn must not be negative.
           */
  __STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
           {
                  if ((int32_t)(IRQn) >= 0)
                 {
                      NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
                 }
           }
          NVIC内存映射地址:
          #define NVIC                ((NVIC_Type      *)     NVIC_BASE     )   /*!< NVIC configuration struct */
#define NVIC_BASE           (SCS_BASE +  0x0100UL)                    /*!< NVIC Base Address */
            #define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address */
          NVIC结构体的定义:
          /**
               \ingroup    CMSIS_core_register
               \defgroup   CMSIS_NVIC  Nested Vectored Interrupt Controller (NVIC)
               \brief      Type definitions for the NVIC Registers
               @{
          */

          typedef struct
          {
                __IOM uint32_t ISER[8U];               /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register */
                          uint32_t RESERVED0[24U];
                __IOM uint32_t ICER[8U];               /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register */
                          uint32_t RSERVED1[24U];
                __IOM uint32_t ISPR[8U];               /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register */
                          uint32_t RESERVED2[24U];
                __IOM uint32_t ICPR[8U];               /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register */
                          uint32_t RESERVED3[24U];
                __IOM uint32_t IABR[8U];               /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register */
                          uint32_t RESERVED4[56U];
                __IOM uint8_t  IP[240U];               /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
                          uint32_t RESERVED5[644U];
                __OM  uint32_t STIR;                   /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register */
            }  NVIC_Type;


           ISER映射的地址就是:0xE000E100UL   
这个地址在RT1052手册中没有找到,从上面的定义说明可以看出来,这是CMSIS_core_register 内核寄存器。
          没有找到M7内核资料,从Cortex-M3权威指南中找到相关寄存器:
             <ignore_js_op>
             <ignore_js_op>
             <ignore_js_op>

            
        2.2.3、GPIO_PortEnableInterrupts(EXAMPLE_SW_GPIO, 1U << EXAMPLE_SW_GPIO_PIN);
            这个函数在fsl_gpio.c中定义
            void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config)
            {
                #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
                 /* Enable GPIO clock. */
                CLOCK_EnableClock(s_gpioClock[GPIO_GetInstance(base)]);
                #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */

                 /* Register reset to default value */
                 base->IMR &= ~(1U << pin);        

                 /* Configure GPIO pin direction */
                 if (Config->direction == kGPIO_DigitalInput)     //GPIO设置为输入
                 {
                      base->GDIR &= ~(1U << pin);
                 }
                 else
                 {
                       GPIO_PinWrite(base, pin, Config->outputLogic);
                       base->GDIR |= (1U << pin);
                  }

                  /* Configure GPIO pin interrupt mode */
                  GPIO_SetPinInterruptConfig(base, pin, Config->interruptMode);  //配置中断模式,程序开始就设置为上升沿中断模式
             }
            RT1052手册中有关GPIO中断配置相关的寄存器
             <ignore_js_op>
             <ignore_js_op>
             <ignore_js_op>
    三、实验结果:
        通过对上面寄存器的分析,对GPIO中断配置有了新的认识。
         <ignore_js_op>

posted on 2022-06-15 21:12  张凌001  阅读(106)  评论(0编辑  收藏  举报

导航