4. 外部中断控制LED
任务目标
本案例基于GD32V开发板,通过按键触发外部中断(EXTI),在中断服务函数中翻转LED的亮灭状态。核心目标是理解RISC-V中断向量、EXTI外部中断配置流程以及中断服务函数的编写与注册方法。
硬件连接
- LED:连接到PA7(低电平点亮)
- 按键:连接到PA0(按下为低电平),PA0同时复用为EXTI0输入
核心实现
代码基于GD32V官方固件库,完整实现EXTI0中断配置与LED翻转逻辑。关键配置步骤包括:使能GPIO与AFIO时钟、配置PA0为输入模式并连接到EXTI0、设置EXTI触发方式为下降沿、配置NVIC中断优先级并使能EXTI0中断。
#include "gd32vf103.h"
void led_gpio_init(void) {
/* 使能GPIOA时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
/* 配置PA7为推挽输出,最大速度50MHz */
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
/* 初始状态:LED灭(PA7输出高电平) */
gpio_bit_set(GPIOA, GPIO_PIN_7);
}
void exti_key_init(void) {
/* 使能GPIOA和AFIO时钟 */
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
/* 配置PA0为下拉输入 */
gpio_init(GPIOA, GPIO_MODE_IN_PD, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
/* 将PA0连接到EXTI0 */
gpio_exti_source_select(GPIO_EVENT_PORT_GPIOA, GPIO_EVENT_PIN_0);
/* 配置EXTI0:下降沿触发 */
exti_init(EXTI_0, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_flag_clear(EXTI_0);
/* 配置NVIC:使能EXTI0中断,优先级1 */
nvic_irq_enable(EXTI0_IRQn, 1, 0);
}
void EXTI0_IRQHandler(void) {
/* 检查EXTI0中断标志 */
if (exti_interrupt_flag_get(EXTI_0)) {
/* 翻转PA7输出状态 */
gpio_bit_write(GPIOA, GPIO_PIN_7,
(gpio_input_bit_get(GPIOA, GPIO_PIN_7) == RESET) ? SET : RESET);
/* 清除中断标志 */
exti_interrupt_flag_clear(EXTI_0);
}
}
int main(void) {
led_gpio_init();
exti_key_init();
while (1) {
/* 主循环为空,等待外部中断触发 */
}
}
编译与烧录
使用RISC-V GCC工具链编译,通过OpenOCD和JTAG调试器烧录到GD32V开发板:
# 编译(假设项目文件位于当前目录)
riscv-none-embed-gcc -march=rv32imac -mabi=ilp32 -O2 -T gd32vf103_flash.ld \
-o exti_led.elf main.c startup_gd32vf103.s system_gd32vf103.c \
-I./ -L./ -lgd32vf103
# 生成hex文件
riscv-none-embed-objcopy -O ihex exti_led.elf exti_led.hex
# 通过OpenOCD烧录
openocd -f interface/ftdi/jtag-lock-pick_tiny_2.cfg \
-f target/gd32vf103.cfg \
-c "program exti_led.hex verify reset exit"
验证方法
烧录成功后,按下连接在PA0的按键,每次按下时LED(PA7)的亮灭状态应翻转一次。具体判定标准:
- 上电后LED处于熄灭状态(PA7输出高电平)
- 第一次按下按键,LED点亮(PA7输出低电平)
- 第二次按下按键,LED熄灭
- 重复按键,LED状态始终跟随按键动作翻转,无遗漏或抖动导致的异常翻转
若LED状态不变化,可通过调试器检查EXTI0_IRQHandler是否被触发,以及PA0引脚电平是否在按键按下时正确拉低。
关键机制说明
本案例的中断响应路径为:按键按下→PA0电平下降→EXTI0检测到下降沿→置位中断标志→NVIC响应中断→跳转到EXTI0_IRQHandler执行→翻转LED后清除中断标志。RISC-V内核通过中断向量表定位到对应的处理函数,GD32V的固件库已封装好向量表跳转逻辑,开发者只需实现与中断号匹配的IRQHandler函数即可。