PY32F003F18外部中断回调函数

PY32F003F18的GPIO外部中断源:EXTI0_1_IRQn,EXTI2_3_IRQn和EXTI4_15_IRQn,与之对应的中断函数为EXTI0_1_IRQHandler(),EXTI2_3_IRQHandler()和EXTI4_15_IRQHandler()。

PY32F003F18的外部中断服务函数通过调用HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin),才能实现调用其Callback函数HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)。

因此,HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)和HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)是外部中断调用的公共函数。函数原型如下:

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
        //GPIOx外部中断回调函数
  }
}

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(GPIO_Pin);

  /* NOTE: This function should not be modified, when the callback is needed,
            the HAL_GPIO_EXTI_Callback could be implemented in the user file
   */

}

HAL_GPIO_EXTI_Callback()需要用户自己去构建

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin==GPIO_PIN_0)//处理外部中断0
    {
        EXTI0_LED_Toggle();
    }
    if(GPIO_Pin==GPIO_PIN_1)//处理外部中断1
    {
        EXTI1_LED_Toggle();
    }
    if(GPIO_Pin==GPIO_PIN_2)//处理外部中断2
    {
        EXTI0_LED_Toggle();
    }
    if(GPIO_Pin==GPIO_PIN_3)//处理外部中断3
    {
        EXTI1_LED_Toggle();
    }
}

//函数功能:GPIO0~GPIO1外部中断服务程序
void EXTI0_1_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
}

这种做法,实现了外部中断统一管理,缺点是中断程序之间出现了交叉,其次执行效率降低了,再次也不是很直观。对于不清楚HAL库程序管理的人来说,确实是一个坑。如果我们不用HAL_GPIO_EXTI_IRQHandler(),也可以实现。
//函数功能:GPIO0~GPIO1外部中断服务程序
void EXTI0_1_IRQHandler(void)
{
///HAL_GPIO_EXTI_Callback开始
    if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != 0x00u)
  {//读"GPIO_PIN_0事件挂起标志位",当软件或者硬件产生上升沿/下降沿触发事件时,该位置位。
        EXTI0_LED_Toggle();//输出电平翻转
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);//清除外部事件标志位
        //清除"GPIO_PIN_0外部事件标志位"
        //当软件或者硬件产生上升沿/下降沿触发事件时,该位置位;

  }
    if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_1) != 0x00u)
  {//读"GPIO_PIN_1事件挂起标志位",当软件或者硬件产生上升沿/下降沿触发事件时,该位置位。
        EXTI1_LED_Toggle();//输出电平翻转
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);//清除外部事件标志位
        //清除"GPIO_PIN_1外部事件标志位"
        //当软件或者硬件产生上升沿/下降沿触发事件时,该位置位;

  }
    NVIC_ClearPendingIRQ(EXTI0_1_IRQn);//清除EXTI0_1_IRQn中断源的中断标志位
///HAL_GPIO_EXTI_Callback结束
}

通过两个程序对比,后者更具有可读性。

#include "EXTI.h"
#include "LED.h"

void EXTI0_Init(void);
void EXTI12_Init(void);

//函数功能:将PA0引脚配置为外部中断引脚
void EXTI0_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructureure;

  __HAL_RCC_GPIOA_CLK_ENABLE();  //GPIOA时钟使能

  GPIO_InitStructureure.Pin = GPIO_PIN_0;//选择第0脚
	GPIO_InitStructureure.Pull = GPIO_PULLUP;//引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_MEDIUM;//配置GPIO速度为中速
	GPIO_InitStructureure.Mode   = GPIO_MODE_IT_FALLING;//配置为下降沿检测模式
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//因为使用了GPIO_MODE_IT_FALLING,所以使能了外部中断线


	HAL_NVIC_SetPriority(EXTI0_1_IRQn,0x03,0);
	//EXTI0_1_IRQn表示外部中断线0~中断线1,EXTI0_1_IRQn
	//设置中断优先级为0x03,0无意义,注意:0<=PreemptPriority<=3,值越大,表示中断优先级越低
	//Enable and set Button EXTI Interrupt to the lowest priority

	HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
	//EXTI0_1_IRQn表示外部中断线0~中断线1,EXTI0_1_IRQn
	//使能EXTI0_1_IRQn中断
}

//函数功能:将PA1引脚配置为外部中断引脚
void EXTI1_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructureure;

  __HAL_RCC_GPIOA_CLK_ENABLE();  //GPIOA时钟使能

  GPIO_InitStructureure.Pin = GPIO_PIN_1;//选择第1脚
	GPIO_InitStructureure.Pull = GPIO_PULLUP;//引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_MEDIUM;//配置GPIO速度为中速
	GPIO_InitStructureure.Mode   = GPIO_MODE_IT_FALLING;//配置为下降沿检测模式
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//因为使用了GPIO_MODE_IT_FALLING,所以使能了外部中断线


	HAL_NVIC_SetPriority(EXTI0_1_IRQn,0x03,0);
	//EXTI0_1_IRQn表示外部中断线0~中断线1,EXTI0_1_IRQn
	//设置中断优先级为0x03,0无意义,注意:0<=PreemptPriority<=3,值越大,表示中断优先级越低
	//Enable and set Button EXTI Interrupt to the lowest priority

	HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
	//EXTI0_1_IRQn表示外部中断线0~中断线1,EXTI0_1_IRQn
	//使能EXTI0_1_IRQn中断
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin==GPIO_PIN_0)//处理外部中断0
	{
		EXTI0_LED_Toggle();
	}
	if(GPIO_Pin==GPIO_PIN_1)//处理外部中断1
	{
		EXTI1_LED_Toggle();
	}
	if(GPIO_Pin==GPIO_PIN_2)//处理外部中断2
	{
		EXTI0_LED_Toggle();
	}
	if(GPIO_Pin==GPIO_PIN_3)//处理外部中断3
	{
		EXTI1_LED_Toggle();
	}
}

//函数功能:GPIO0~GPIO1外部中断服务程序
//void EXTI0_1_IRQHandler(void)
//{
//	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
//	HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
//}

//函数功能:GPIO0~GPIO1外部中断服务程序
void EXTI0_1_IRQHandler(void)
{
///HAL_GPIO_EXTI_Callback开始
	if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != 0x00u)
  {//读"GPIO_PIN_0事件挂起标志位",当软件或者硬件产生上升沿/下降沿触发事件时,该位置位。
		EXTI0_LED_Toggle();//输出电平翻转
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);//清除外部事件标志位
		//清除"GPIO_PIN_0外部事件标志位"
		//当软件或者硬件产生上升沿/下降沿触发事件时,该位置位;
  }
	if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_1) != 0x00u)
  {//读"GPIO_PIN_1事件挂起标志位",当软件或者硬件产生上升沿/下降沿触发事件时,该位置位。
		EXTI1_LED_Toggle();//输出电平翻转
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);//清除外部事件标志位
		//清除"GPIO_PIN_1外部事件标志位"
		//当软件或者硬件产生上升沿/下降沿触发事件时,该位置位;
  }
	NVIC_ClearPendingIRQ(EXTI0_1_IRQn);//清除EXTI0_1_IRQn中断源的中断标志位
///HAL_GPIO_EXTI_Callback结束
}

你可能感兴趣的:(产品研发,单片机,嵌入式硬件,PY32F003F18,国产ARM)