①初始化GPIO;
②初始化NVIC;;
③初始化EXTI
④编写中断服务函数。
①初始化GPIO
- 开启所有外部中断源管脚对应的GPIO时钟和AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx|RCC_APB2Periph_AFIO, ENABLE)
- 定义GPIO初始化结构变量,
GPIO_InitTypeDef GPIO_InitStructure;
- 赋值结构变量各成员
GPIO_InitStructure.GPIO_Pin=管脚号0~15 ; .mode= GPIO_Mode_IN_FLOATING(浮空输入);
- 调用GPIO初始化函数:GPIO_Init(& GPIO_InitStructure);
- 如果有多个中断源,重复步骤3~4。
②初始化NVIC;
- 设置优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_n);
- 定义NVIC初始化结构变量,并赋值结构变量各成员
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel =中断号;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =抢占优先级;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =子优先级;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- 调用NVIC初始化函数。
NVIC_Init(&NVIC_InitStructure);
- 如果有多个中断源,重复步骤2~3
③初始化EXTI
- 定义EXTI初始化结构变量 EXTI_InitTypeDef EXTI_InitStructure;
- 选择EXTI的信号源,设置外部中断配置寄存器AFIO_EXTICR相关位
GPIO_EXTILineConfig()
- 赋值结构变量各成员
EXTI_InitStructure.EXTI_Line =信号源
EXTI_InitStructure.EXTI_Mode =中断模式
EXTI_InitStructure.EXTI_Trigger =触发方式
- 调用EXTI初始化函数
EXTI_Init(&EXTI_InitStructure);
如果有多个外部中断源,重复步骤2~4.
④编写中断服务函数。
• 在启动文件startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理,可以把中断服务函数统一写在stm32f10x_it.c 这个库文件中。
• 关于中断服务函数的函数名必须跟启动文件里面预先设置的一样,如果写错,系统就在中断向量表中找不到中断服务函数的入口,直接跳转到启动文件里面预先写好的空函数,并且在里面无限循环,实现不了中断。
• 对每个中断号编写中断服务函数,对于EXTI9-5 和EXTI15-10,多个中断源公用同一个中断号时,可以在中断服务函数中判断具体是哪一个中断源被触发,然后根据中断源编制相应的响应程序。
void EXTIx_IRQHandler(void); void EXTI9_5_IRQHandler(void)
• 重要提醒,中断服务函数中,为确保确实产生了中断请求,通常需要检查一下状态标识位确认确实产生了该中断。同时,为避免一次中断请求执行多次中断服务程序,中断服务程序最后需要清除该中断标识位。例如:
if(EXTI_GetITStatus(KEY3_INT_EXTI_LINE) != RESET) //确保是否产生了EXTI Line中断
{…
EXTI_ClearITPendingBit(KEY3_INT_EXTI_LINE); //清除中断标志位
}