GD32F4:外部中断

一、名词解释

NVIC:嵌套向量中断控制器,全称Nested vectored interrupt controller。

EXTI:外部中断和事件控制器。

二、优先级

2.1 中断分组(不建议看)

一般情况下中断分为5组,如下图1。当优先级分组为3时,该组所有的中断有三位设置抢占优先级,范围为0~7,有一位设置子优先级,范围0~1,数值越小,优先级越高。中断分组在HAL库初始化中被HAL_Init()设置,一般情况下不需要去修改。

GD32F4:外部中断_第1张图片

图1 中断分组设置表

中断分组不建议看的原因与抢占优先级与子优先级有关,例如上面提到的分组3,在实际使用中中断优先级、子优先级均超过对应范围,在这种情况下不会报错也不会出现警告,也就是说中断分组对我使用外部中断造成了困扰,因此我不建议了解本部分内容。

2.2 中断优先级

中断优先级可以分为抢占式优先级和响应优先级(子优先级),每个中断源都需要被指定这两种优先级。抢占优先级高的中断可以打断正在执行的抢占优先级低的中断;抢占优先级相同情况下,子优先级高的中断不能打断子优先级低的中断。

2.3 EXT线

EXTI:外部中断和事件控制器,是由20个产生事件/中断请求的边沿检测器组成。每一条输入线都可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

EXTI支持23个外部中断/事件请求,这些都是信息输入端,也就是上面提及到了输入线,具体如下:

EXTI线0~15:对应外部IO口的输入中断

EXTI线16:连接到PVD输出

EXTI线17:连接到RTC闹钟事件

EXTI线18:连接到USB唤醒事件

EXTI线19:连接到以太网唤醒事件

EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件

EXTI线21:连接到RTC入侵和时间戳事件

EXTI线22:连接到RTC唤醒事件

从上面可以看出,GD32供给IO口使用的中断线只有16个,但是STM32F407的IO口却远远不止16个,所以STM32把GPIO管脚GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线0~15。这样子每个中断线对应了最多7个IO口,而中断线每次只能连接到1个IO口上,这样就需要通过配置决定对应的中断线配置到哪个GPIO上了。

例:PA0对应的中断线是0,对应的中断服务函数是EXTI0_IRQHandler();PE4对应的中断线是4, 对应的中断服务函数是EXTI0_IRQHandler();

三、 API函数与外部中断配置步骤

3.1 API函数

/********************************************************
 * 函数描述:设置中断的优先级分组。
 * 函数形参:PriorityGroup,中断优先级分组号,NVIC_PRIORITYGROUP_0到
NVIC_PRIORITYGROUP_4(共5组)。
 * 返回值:无
*********************************************************/
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);


/********************************************************
 * 函数描述:用于设置中断的抢占优先级和响应优先级(子优先级)。
 * 函数形参:IRQn,中断号,可以选择范围在IRQn_Type定义的枚举类型中
 *          PreemptPriority:是抢占优先级,0~15
 *          SubPriority:响应优先级,0~15
 * 返回值:无
*********************************************************/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);


/********************************************************
 * 函数描述:用于使能中断。
 * 函数形参:IRQn,中断号,可以选择范围在IRQn_Type定义的枚举类型中
 * 返回值:无
*********************************************************/
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);

3.2 外部中断配置步骤

  1. 使能IO口时钟;
  2. 设置IO口,触发条件,开启SYSCFG时钟,设置IO口与中断线的映射关系;
  3. 配置中断优先级,并使能中断;
  4. 编写中断服务函数
  5. 编写中断处理回调函数HAL_GPIO_EXTI_Callback

四、代码

4.1 设置PA0、PE4为输入

//按键初始化函数
void KEY_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();           //开启GPIOA时钟
    __HAL_RCC_GPIOE_CLK_ENABLE();           //开启GPIOE时钟

    
    GPIO_Initure.Pin=GPIO_PIN_0;            //PA0
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLDOWN;        //下拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
    
	  GPIO_Initure.Pin=GPIO_PIN_4;            //PE4
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLDOWN;        //下拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOE,&GPIO_Initure);    
}

//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
//1,KEY0按下
//2,KEY_UP按下 即WK_UP
//注意此函数有响应优先级,KEY0>KEY_UP!!
u8 KEY_Scan(u8 mode)
{
    static u8 key_up=1;     //按键松开标志
    if(mode==1)key_up=1;    //支持连按
    if(key_up&&(KEY0==1||WK_UP==1))
    {
        delay_ms(10);       //去抖动
        key_up=0;
        if(KEY0==1)       return KEY0_PRES;
        else if(WK_UP==1) return WKUP_PRES;          
    }else if(KEY0==0&&WK_UP==0)key_up=1;
    return 0;   //无按键按下
}

4.2 复用为外部中断

//外部中断初始化
void EXTI_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();               //开启GPIOA时钟
    __HAL_RCC_GPIOE_CLK_ENABLE();               //开启GPIOE时钟
    
    GPIO_Initure.Pin=GPIO_PIN_0;                //PA0
    GPIO_Initure.Mode=GPIO_MODE_IT_RISING;      //上升沿触发
    GPIO_Initure.Pull=GPIO_PULLDOWN;
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
    
    GPIO_Initure.Pin=GPIO_PIN_4; 				//PE4
    GPIO_Initure.Mode=GPIO_MODE_IT_RISING;      //上升沿触发
    GPIO_Initure.Pull=GPIO_PULLDOWN;
    HAL_GPIO_Init(GPIOE,&GPIO_Initure);
    
    //中断线0-PA0
    HAL_NVIC_SetPriority(EXTI0_IRQn,0,2);       //抢占优先级为0,子优先级为2
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);             //使能中断线0
    
    //中断线4-PE4
    HAL_NVIC_SetPriority(EXTI4_IRQn,1,2);   	  //抢占优先级为1,子优先级为2
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);         	  //使能中断线4
}


//中断服务函数,PA0用线0
void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);		//调用中断处理公用函数
}

//PE4用线4
void EXTI4_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);		//调用中断处理公用函数
}

//中断服务程序中需要做的事情
//在HAL库中所有的外部中断服务函数都会调用此函数
//GPIO_Pin:中断引脚号
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    delay_ms(100);      //消抖
    switch(GPIO_Pin)
    {
        case GPIO_PIN_0:
            if(WK_UP==1) 
            {
				LED1=!LED1;//控制LED1翻转
            }
            break;
        case GPIO_PIN_4:
            if(KEY0==1)  
            {
				LED0=!LED0;//控制LED0翻转
            }
            break;
    }
}

你可能感兴趣的:(单片机,嵌入式硬件)