3. 外部中断控制LED

外部中断控制LED 学习卡片

任务说明

本案例基于中微CMS32系列车规MCU,实现外部中断控制LED翻转。使用板载按键(连接至外部中断引脚)作为触发源,每次按下按键触发一次外部中断,在中断服务函数中翻转LED的亮灭状态。通过本案例掌握CMS32的GPIO外部中断配置流程、中断服务函数编写方法以及中断标志的清除操作。

硬件连接

  • LED:连接至PB5引脚(输出模式,高电平点亮)
  • 按键:连接至PA2引脚(外部中断输入,下降沿触发)

代码实现


#include "CMS32L051.h"

/* 中断服务函数声明 */
void EXTI2_IRQHandler(void);

/* LED引脚定义 */
#define LED_PORT       GPIOB
#define LED_PIN        GPIO_PIN_5

/* 按键中断引脚定义 */
#define KEY_EXTI_PORT  GPIOA
#define KEY_EXTI_PIN   GPIO_PIN_2
#define KEY_EXTI_LINE  EXTI_LINE_2

/* 简单延时函数 */
void delay_ms(uint32_t ms)
{
    uint32_t i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 8000; j++);
}

/* GPIO初始化 */
void GPIO_Init(void)
{
    /* 使能GPIOA和GPIOB时钟 */
    CGC->PERCLKEN |= CGC_PERCLKEN_GPIOA_MASK | CGC_PERCLKEN_GPIOB_MASK;
    
    /* 配置PB5为推挽输出,用于驱动LED */
    GPIOB->CFG &= ~(0xF << (5 * 4));          /* 清除PB5配置 */
    GPIOB->CFG |= (0x3 << (5 * 4));           /* 设置为推挽输出 */
    
    /* 配置PA2为输入模式,用于外部中断 */
    GPIOA->CFG &= ~(0xF << (2 * 4));          /* 清除PA2配置 */
    GPIOA->CFG |= (0x0 << (2 * 4));           /* 设置为浮空输入 */
    
    /* 初始LED为熄灭状态 */
    GPIOB->ODR |= (1 << 5);                   /* 输出高电平,LED灭 */
}

/* 外部中断初始化 */
void EXTI_Init(void)
{
    /* 使能SYSCFG时钟(用于外部中断配置) */
    CGC->PERCLKEN |= CGC_PERCLKEN_SYSCFG_MASK;
    
    /* 选择PA2作为EXTI2的输入源 */
    SYSCFG->EXTICR[0] &= ~(0xF << (2 * 4));
    SYSCFG->EXTICR[0] |= (0x0 << (2 * 4));   /* 选择GPIOA */
    
    /* 配置下降沿触发 */
    EXTI->FTSR |= (1 << 2);                   /* 使能下降沿触发 */
    EXTI->RTSR &= ~(1 << 2);                  /* 禁用上升沿触发 */
    
    /* 清除中断标志 */
    EXTI->PR |= (1 << 2);
    
    /* 使能EXTI2中断 */
    EXTI->IMR |= (1 << 2);
    
    /* 配置NVIC优先级并使能中断 */
    NVIC_SetPriority(EXTI2_IRQn, 2);
    NVIC_EnableIRQ(EXTI2_IRQn);
}

/* 外部中断2服务函数 */
void EXTI2_IRQHandler(void)
{
    /* 检查EXTI2中断标志 */
    if (EXTI->PR & (1 << 2))
    {
        /* 翻转LED状态 */
        GPIOB->ODR ^= (1 << 5);
        
        /* 清除中断标志 */
        EXTI->PR |= (1 << 2);
    }
}

/* 主函数 */
int main(void)
{
    /* 系统时钟初始化(默认使用内部RC) */
    SystemInit();
    
    /* 初始化GPIO */
    GPIO_Init();
    
    /* 初始化外部中断 */
    EXTI_Init();
    
    while (1)
    {
        /* 主循环空操作,等待中断触发 */
        __NOP();
    }
}

代码说明

代码首先完成GPIO初始化:PB5配置为推挽输出驱动LED,PA2配置为浮空输入作为外部中断引脚。外部中断初始化部分选择PA2作为EXTI2的输入源,配置为下降沿触发(按键按下时产生下降沿),并使能中断线和NVIC中断通道。中断服务函数中检测EXTI2标志位后翻转LED输出状态,最后清除中断标志以准备下一次触发。主循环为空操作,系统在中断驱动下工作。

编译与烧录


/* 使用Keil MDK或IAR打开工程,编译生成hex文件 */
/* 通过CMS32-Link调试器烧录至目标板 */

验证方法

将程序烧录至开发板后,观察LED初始状态为熄灭。每次按下按键,LED状态应翻转一次(亮→灭或灭→亮)。连续快速按键时,每次按键都应产生一次中断并翻转LED。若LED状态未变化,可通过调试器在中断服务函数中设置断点,检查是否进入中断以及中断标志是否被正确清除。

判定标准

  • LED初始为熄灭状态
  • 每次按下按键,LED状态翻转一次
  • 中断服务函数中标志位检测与清除逻辑正确
  • 松开按键(上升沿)不触发中断
外部中断控制LED — 中断触发流程 按键按下 PA2 下降沿 EXTI2 触发 硬件置位标志 NVIC 响应 跳转中断服务 ISR 执行 翻转LED EXTI2_IRQHandler 内部流程 检查 PR 位 bit2 翻转 ODR bit5 写1清除 PR bit2 返回 图例 硬件触发 中断响应 ISR操作