战舰开发板V4——外部中断

战舰开发板V4——外部中断

image-20260731212235671

image-20260731212500636

image-20260731213653871

image-20260731213713980

image-20260731214153182

image-20260731220131754
什么是 NVIC? NVIC 即嵌套向量中断控制器,全称 Nested vectored interrupt controller。

X:Y = 4 个优先级位里面,X 个位用来控制能不能抢中断,Y 个位控制同时来了谁先跑。

  1. EXTI0_IRQHandlerEXTI0(1 根线)
  2. EXTI1_IRQHandlerEXTI1(1 根线)
  3. EXTI2_IRQHandlerEXTI2(1 根线)
  4. EXTI3_IRQHandlerEXTI3(1 根线)
  5. EXTI4_IRQHandlerEXTI4(1 根线)
  6. EXTI9_5_IRQHandlerEXTI5、EXTI6、EXTI7、EXTI8、EXTI9(5 根线共用)
  7. EXTI15_10_IRQHandlerEXTI10、EXTI11、EXTI12、EXTI13、EXTI14、EXTI15(6 根线共用)

总数:1+1+1+1+1+5+6 = 16 根外部中断线

image-20260731231512697

#include "Exti.h"


/**
 * @brief       KEY0 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY0_INT_IRQHandler(void)
{
    /* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */
    HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN); 
    /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);         
}

/**
 * @brief       KEY1 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY1_INT_IRQHandler(void)
{ 
      /* 调用中断处理公用函数 清除KEY1所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    HAL_GPIO_EXTI_IRQHandler(KEY1_INT_GPIO_PIN);  
     /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY1_INT_GPIO_PIN);        
}

/**
 * @brief       KEY2 外部中断服务程序
 * @param       无
 * @retval      无
 */
void KEY2_INT_IRQHandler(void)
{ 
    /* 调用中断处理公用函数 清除KEY2所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    HAL_GPIO_EXTI_IRQHandler(KEY2_INT_GPIO_PIN); 
    /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    __HAL_GPIO_EXTI_CLEAR_IT(KEY2_INT_GPIO_PIN);        
}

/**
 * @brief       WK_UP 外部中断服务程序
 * @param       无
 * @retval      无
 */
void WKUP_INT_IRQHandler(void)
{ 
    /* 调用中断处理公用函数 清除KEY_UP所在中断线 的中断标志位,中断下半部在HAL_GPIO_EXTI_Callback执行 */
    HAL_GPIO_EXTI_IRQHandler(WKUP_INT_GPIO_PIN); 
    /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
    __HAL_GPIO_EXTI_CLEAR_IT(WKUP_INT_GPIO_PIN);        
}

/**
 * @brief       中断服务程序中需要做的事情
                在HAL库中所有的外部中断服务函数都会调用此函数
 * @param       GPIO_Pin:中断引脚号
 * @retval      无
 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(20);      /* 消抖 */
    switch(GPIO_Pin)
    {
        case KEY0_INT_GPIO_PIN:
            if (KEY0 == 0)
            {
                LED0_TOGGLE();  /* LED0 状态取反 */ 
                LED1_TOGGLE();  /* LED1 状态取反 */ 
            }
            break;
        case KEY1_INT_GPIO_PIN:
            if (KEY1 == 0)
            {
                LED0_TOGGLE();  /* LED0 状态取反 */ 
            }
            break;
        case KEY2_INT_GPIO_PIN:
            if (KEY2 == 0)
            {
                LED1_TOGGLE();  /* LED1 状态取反 */ 
            }
            break;
        case WKUP_INT_GPIO_PIN:
            if (WK_UP == 1)
            {
                BEEP_TOGGLE();  /* 蜂鸣器状态取反 */ 
            }
            break;
    }
}

/**
 * @brief       外部中断初始化程序
 * @param       无
 * @retval      无
 */
void Extix_init(void)
{
    GPIO_InitTypeDef GPIO_Init_Struct;

    KEY0_GPIO_CLK_ENABLE();                                  /* KEY0时钟使能 */
    KEY1_GPIO_CLK_ENABLE();                                  /* KEY1时钟使能 */
    KEY2_GPIO_CLK_ENABLE();                                  /* KEY2时钟使能 */
    WKUP_GPIO_CLK_ENABLE();                                  /* WKUP时钟使能 */

    GPIO_Init_Struct.Pin = KEY0_INT_GPIO_PIN;
    GPIO_Init_Struct.Mode = GPIO_MODE_IT_FALLING;            /* 下升沿触发 */
    GPIO_Init_Struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY0_INT_GPIO_PORT, &GPIO_Init_Struct);    /* KEY0配置为下降沿触发中断 */

    GPIO_Init_Struct.Pin = KEY1_INT_GPIO_PIN;
    GPIO_Init_Struct.Mode = GPIO_MODE_IT_FALLING;            /* 下升沿触发 */
    GPIO_Init_Struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_Init_Struct);    /* KEY1配置为下降沿触发中断 */
    
    GPIO_Init_Struct.Pin = KEY2_INT_GPIO_PIN;
    GPIO_Init_Struct.Mode = GPIO_MODE_IT_FALLING;            /* 下升沿触发 */
    GPIO_Init_Struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_Init_Struct);    /* KEY2配置为下降沿触发中断 */
    
    GPIO_Init_Struct.Pin = WKUP_INT_GPIO_PIN;
    GPIO_Init_Struct.Mode = GPIO_MODE_IT_RISING;             /* 上升沿触发 */
    GPIO_Init_Struct.Pull = GPIO_PULLDOWN;
    HAL_GPIO_Init(WKUP_GPIO_PORT, &GPIO_Init_Struct);        /* WKUP配置为下降沿触发中断 */

    HAL_NVIC_SetPriority(KEY0_INT_IRQn, 0, 2);               /* 抢占0,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY0_INT_IRQn);                       /* 使能中断线1 */

    HAL_NVIC_SetPriority(KEY1_INT_IRQn, 1, 2);               /* 抢占1,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY1_INT_IRQn);                       /* 使能中断线15 */
    
    HAL_NVIC_SetPriority(KEY2_INT_IRQn, 2, 2);               /* 抢占2,子优先级2 */
    HAL_NVIC_EnableIRQ(KEY2_INT_IRQn);                       /* 使能中断线15 */

    HAL_NVIC_SetPriority(WKUP_INT_IRQn, 3, 2);               /* 抢占3,子优先级2 */
    HAL_NVIC_EnableIRQ(WKUP_INT_IRQn);                       /* 使能中断线0 */
}

#ifndef __EXTI_H
#define __EXTI_H

#include "Delay.h"
#include "Led.h"
#include "Beep.h"
#include "Key.h"


/* 引脚 和 中断编号 & 中断服务函数 定义 */ 

#define KEY0_INT_GPIO_PORT              GPIOE
#define KEY0_INT_GPIO_PIN               GPIO_PIN_4
#define KEY0_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY0_INT_IRQn                   EXTI4_IRQn
#define KEY0_INT_IRQHandler             EXTI4_IRQHandler

#define KEY1_INT_GPIO_PORT              GPIOE
#define KEY1_INT_GPIO_PIN               GPIO_PIN_3
#define KEY1_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY1_INT_IRQn                   EXTI3_IRQn
#define KEY1_INT_IRQHandler             EXTI3_IRQHandler

#define KEY2_INT_GPIO_PORT              GPIOE
#define KEY2_INT_GPIO_PIN               GPIO_PIN_2
#define KEY2_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */
#define KEY2_INT_IRQn                   EXTI2_IRQn
#define KEY2_INT_IRQHandler             EXTI2_IRQHandler

#define WKUP_INT_GPIO_PORT              GPIOA
#define WKUP_INT_GPIO_PIN               GPIO_PIN_0
#define WKUP_INT_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 */
#define WKUP_INT_IRQn                   EXTI0_IRQn
#define WKUP_INT_IRQHandler             EXTI0_IRQHandler


void Extix_init(void);  /* 外部中断初始化 */

#endif

posted @ 2026-07-31 23:45  Q&25  阅读(2)  评论(0)    收藏  举报