GD32F4外部中断详解及应用案例
一、NVIC中断系统
Cortex-M4集成了嵌套式矢量型中断控制器(Nested Vectored Interrupt Controller,NVIC)来实现高效的异常和中断处理。
中断系统包含外部中断、定时器中断、DMA中断和串口中断等。
二、EXTI外部中断
EXTI(中断/事件控制器)包括23个相互独立的边沿检测电路并且能够向处理器内核产生中断请求或唤醒事件。
EXTI有三种触发类型:上升沿触发、下降沿触发和任意沿触发。
三、中断触发源
EXTI触发源包括来自I/O管脚的16根线以及来自内部模块的7根线,包括LVD、RTC闹钟、USB唤醒、以太网唤醒、RTC侵入和时间戳、RTC唤醒。
通过配置SYSCFG_EXTISSx寄存器,所有的GPIO管脚都可以被选作EXTI的触发源。
同一个EXTI线下的GPIO管脚不能同时触发,只能选择一个GPIO管脚作为该EXTI线的触发源。
四、中断优先级
EXTI的每一个边沿检测电路都可以独立配置和屏蔽,每一个中断都有4位中断优先级配置位,可提供16个中断优先等级。
所有可编程的中断都需要指定抢占优先级和响应优先级,抢占优先级决定是否可以产生中断嵌套,响应优先级决定中断响应程序。若两种优先级一样则看中断在中断向量表中的位置,位置越靠前越优先响应。
可以通过分组设置抢占优先级和响应优先级的位数,中断优先级分组只设置一次,针对的是系统中所有的中断。
五、配置过程
bsp_key.h
#ifndef BSP_KEY_H
#define BSP_KEY_H
#include "gd32f4xx.h"
#include "bsp_led.h"
/* KEY GPIO RCU peripherals */
#define KEY_RCU RCU_GPIOA
/* KEY SYSCFG RCU peripherals */
#define KEY_SYSCFR_RCU RCU_SYSCFG
/* KEY GPIO port */
#define KEY_GPIO GPIOA
/* KEY GPIO pin */
#define KEY_PIN GPIO_PIN_0
/* KEY GPIO pin mode */
//GPIO_MODE_INPUT : input mode
//GPIO_MODE_OUTPUT: output mode
//GPIO_MODE_AF : alternate function mode
//GPIO_MODE_ANALOG: analog mode
#define KEY_MODE GPIO_MODE_INPUT
/* KEY GPIO pin with pull-up or pull-down resistor */
//GPIO_PUPD_NONE : floating mode, no pull-up and pull-down resistors
//GPIO_PUPD_PULLUP : with pull-up resistor
//GPIO_PUPD_PULLDOWN: with pull-down resistor
#define KEY_PUD GPIO_PUPD_PULLDOWN
/* the NVIC priority group of key exit */
//NVIC_PRIGROUP_PRE0_SUB4:0 bits for pre-emption priority 4 bits for subpriority
//NVIC_PRIGROUP_PRE1_SUB3:1 bits for pre-emption priority 3 bits for subpriority
//NVIC_PRIGROUP_PRE2_SUB2:2 bits for pre-emption priority 2 bits for subpriority
//NVIC_PRIGROUP_PRE3_SUB1:3 bits for pre-emption priority 1 bits for subpriority
//NVIC_PRIGROUP_PRE4_SUB0:4 bits for pre-emption priority 0 bits for subpriority
#define KEY_NVIC_PRIGROUP NVIC_PRIGROUP_PRE2_SUB2
/* the NVIC interrupt request, detailed in IRQn_Type of key exti */
#define KEY_NVIC_IRQ EXTI0_IRQn
/* the pre-emption priority needed to set */
#define KEY_EXIT_PRE_PRIORITY 3U
/* the subpriority needed to set */
#define KEY_EXIT_SUBPRIORITY 3U
/* specify the GPIO port used in EXTI */
#define KEY_EXTI_PORT EXTI_SOURCE_GPIOA
/* specify the EXTI line */
#define KEY_EXTI_PIN EXTI_SOURCE_PIN0
/* EXTI line number, refer to exti_line_enum */
#define KEY_EXTI_LINE_ENUM EXTI_0
/* mode: interrupt or event mode, refer to exti_mode_enum */
//EXTI_INTERRUPT: interrupt mode
//EXTI_EVENT: event mode
#define KEY_EXTI_MODE_ENUM EXTI_INTERRUPT
/* trig_type: interrupt trigger type, refer to exti_trig_type_enum */
//EXTI_TRIG_RISING: rising edge trigger
//EXTI_TRIG_FALLING: falling trigger
//EXTI_TRIG_BOTH: rising and falling trigger
//EXTI_TRIG_NONE: without rising edge or falling edge trigger
#define KEY_EXTI_TRIG_TYPE_ENUM EXTI_TRIG_RISING
/* KEY EXTI IRQHandler */
#define KEY_IRQHandler EXTI0_IRQHandler
extern uint8_t key_exti_flag; /*main.c*/
void key_config(void);
void KEY_IRQHandler(void);
#endif /* BSP_KEY_H */
bsp_key.c
#include "bsp_key.h"
void key_config(void)
{
rcu_periph_clock_enable(KEY_RCU);
rcu_periph_clock_enable(KEY_SYSCFR_RCU);
gpio_mode_set(KEY_GPIO, KEY_MODE, KEY_PUD, KEY_PIN);
nvic_priority_group_set(KEY_NVIC_PRIGROUP);
nvic_irq_enable(KEY_NVIC_IRQ, KEY_EXIT_PRE_PRIORITY, KEY_EXIT_SUBPRIORITY);
syscfg_exti_line_config(KEY_EXTI_PORT, KEY_EXTI_PIN);
exti_init(KEY_EXTI_LINE_ENUM, EXTI_INTERRUPT, KEY_EXTI_TRIG_TYPE_ENUM);
exti_interrupt_enable(KEY_EXTI_LINE_ENUM);
exti_interrupt_flag_clear(KEY_EXTI_LINE_ENUM);
key_exti_flag = 0;
}
void KEY_IRQHandler(void)
{
if(exti_interrupt_flag_get(KEY_EXTI_LINE_ENUM) == SET)
{
key_exti_flag = 1;
exti_interrupt_flag_clear(KEY_EXTI_LINE_ENUM);
}
}