Cortex-M0系列 ~ 外部中断

STM32的每个I/O都可以作为外部中断的中断输入口,每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。这里使用的外部中断来检测按键,下面是相关配置代码~

void EXTIX_Init()
{
    GPIO_InitTypeDef   GPIO_InitStructure;
    EXTI_InitTypeDef   EXTI_InitStructure;
    NVIC_InitTypeDef   NVIC_InitStructure;

    /* Enable Button(GPIOA) clock 使能I/O口时钟*/ 
    RCC_AHBPeriphClockCmd(User_Button_GPIO_CLK, ENABLE);
    /* Enable SYSCFG clock 使能系统时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    //I/O口配置为输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* 外部中断配置 */
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource3);
    EXTI_InitStructure.EXTI_Line    = EXTI_Line3;
    EXTI_InitStructure.EXTI_Mode    = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    /* 中断优先级配置 */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

初始化对I/O口,外部中断线,中断优先级做配置,接着还要编写中断服务函数,A8,M3,M4等都可以自己在中断初始化配置时自定义中断服务函数名,而在M0中只能直接调用库函数给我们准备好的中断函数名。

//上面我们用的是A3脚,所以是触发EXTI2_3_IRQHandler函数
void EXTI2_3_IRQHandler(void)
{
        //检测中断位状态
        if(EXTI_GetITStatus(EXTI_Line3) != RESET)
        {
            //产生中断时的对应操作
            Key_Flag  = true;
            Key_Value1 = 1;

            //产生中断,清除中断位
            EXTI_ClearITPendingBit(EXTI_Line3);
        }
}

EXTI2_3_IRQHandler() 函数为 EXTI_Line2EXTI_Line3 中断线共用,即是PA2、PA3是共用同一个中断服务函数,类似的 EXTI4_15_IRQHandler 是中断线4-15的中断服务函数,这里就有个疑问了,这么多中断线都是跑同一个函数,那要怎么区分不同中断线的操作呢?!细心的朋友可能已经找到答案了~ if(EXTI_GetITStatus(EXTI_Line3) != RESET) 进入中断服务函数后都会先进行一个 if 判断,即检测该中断线是否发生中断,例如我设置了PA2、PA3为两外部中断,那么我的中断服务函数应该是这么写,I/O初始化那些的另行配置

void EXTI2_3_IRQHandler(void)
{
        if(EXTI_GetITStatus(EXTI_Line2) != RESET)
        {
            //code

            //产生中断,清除中断位
            EXTI_ClearITPendingBit(EXTI_Line2);
        }

        if(EXTI_GetITStatus(EXTI_Line3) != RESET)
        {
            //code

            //产生中断,清除中断位
            EXTI_ClearITPendingBit(EXTI_Line3);
        }
}

4-15的中断也是一样的道理,还有注意一点就是中断函数中不要调用延时函数,中断是一个很快的操作,在其中加入延时会引发不必要的错误,可以是修改变量的状态来达到某个目的,但需要考虑项目耦合性。

总结一下使用I/O口外部中断的一般步骤:

  1. 定义结构体,使能I/O、系统时钟
  2. 初始化I/O口为输入
  3. 初始化线上中断,设置触发条件等
  4. 配置中断分组(NVIC),并使能中断
  5. 编写中断服务函数

你可能感兴趣的:(Cortex-M0系列)