开启外部中断的标准步骤
步骤1初始化GPIOGPIO_InitTypeDef GPIO_InitStructure;// 1. 开启GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);// 2. 配置GPIO为输入模式通常是浮空输入或上拉输入GPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;// 上拉输入GPIO_Init(GPIOA,GPIO_InitStructure);步骤2配置AFIO将GPIO映射到EXTI线// 1. 开启AFIO时钟必须RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 2. 将PA0映射到EXTI0线GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);步骤3配置EXTI外部中断线EXTI_InitTypeDef EXTI_InitStructure;// 1. 选择中断线EXTI_InitStructure.EXTI_LineEXTI_Line0;// 对应PA0// 2. 选择模式中断模式或事件模式EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt;// 中断模式// 3. 选择触发方式上升沿、下降沿或双边沿EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Falling;// 下降沿触发// 4. 使能中断线EXTI_InitStructure.EXTI_LineCmdENABLE;// 5. 初始化EXTIEXTI_Init(EXTI_InitStructure);步骤4配置NVIC嵌套向量中断控制器NVIC_InitTypeDef NVIC_InitStructure;// 1. 设置中断分组一般在main函数开头设置一次NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 2位抢占优先级2位响应优先级// 2. 选择要使能的中断通道NVIC_InitStructure.NVIC_IRQChannelEXTI0_IRQn;// EXTI0中断通道// 3. 设置抢占优先级NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;// 4. 设置响应优先级也叫子优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority1;// 5. 使能中断通道NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;// 6. 初始化NVICNVIC_Init(NVIC_InitStructure);步骤5编写中断服务函数voidEXTI0_IRQHandler(void){// 1. 检查是否是EXTI0产生的中断if(EXTI_GetITStatus(EXTI_Line0)!RESET){// 2. 在这里写你的中断处理代码// 比如LED翻转、蜂鸣器响等// 3. 清除中断标志位非常重要EXTI_ClearITPendingBit(EXTI_Line0);}}NVIC是什么有什么作用NVIC全称Nested Vectored Interrupt Controller嵌套向量中断控制器可以把NVIC想象成中断系统的总管家主要负责以下几件事 中断使能/禁能就像一个总开关决定CPU是否响应某个中断即使EXTI配置好了如果NVIC没使能中断也不会执行 优先级管理最重要当多个中断同时发生时NVIC决定先处理谁// 高优先级中断比如紧急停机NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority0;// 低优先级中断比如按键扫描NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority2;优先级的作用抢占优先级可以打断正在执行的低优先级中断响应优先级同抢占优先级时先执行响应优先级高的中断嵌套管理支持高优先级中断打断低优先级中断处理完高优先级后自动返回低优先级继续执行中断向量表映射告诉CPU每个中断对应的处理函数在哪里比如EXTI0中断来了CPU就知道要去执行EXTI0_IRQHandler没有NVIC会怎样如果没有NVIC中断系统会一片混乱多个中断同时发生时不知道先处理谁重要的中断可能被不重要的打断中断来了CPU不知道该去哪执行代码完整示例代码// 外部中断初始化函数PA0下降沿触发voidEXTI0_Init(void){GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 1. 使能时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);// 2. 配置GPIOGPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;GPIO_Init(GPIOA,GPIO_InitStructure);// 3. 配置AFIO映射GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);// 4. 配置EXTIEXTI_InitStructure.EXTI_LineEXTI_Line0;EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmdENABLE;EXTI_Init(EXTI_InitStructure);// 5. 配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitStructure.NVIC_IRQChannelEXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;NVIC_InitStructure.NVIC_IRQChannelSubPriority1;NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_Init(NVIC_InitStructure);}// 中断服务函数voidEXTI0_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line0)!RESET){// 用户代码GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)));EXTI_ClearITPendingBit(EXTI_Line0);}}总结EXTI负责检测外部信号变化产生中断请求NVIC负责管理这些中断请求决定CPU何时、以何种优先级去处理多个中断的初始化代码// 在main函数开头设置一次NVIC分组整个程序只需要设置一次voidNVIC_Config(void){NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 2位抢占优先级2位响应优先级}// 初始化EXTI0PA0voidEXTI0_Init(void){GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 1. 使能GPIOA和AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);// 2. 配置PA0为上拉输入GPIO_InitStructure.GPIO_PinGPIO_Pin_0;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;GPIO_Init(GPIOA,GPIO_InitStructure);// 3. 映射PA0到EXTI0GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);// 4. 配置EXTI0EXTI_InitStructure.EXTI_LineEXTI_Line0;EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Falling;// 下降沿触发EXTI_InitStructure.EXTI_LineCmdENABLE;EXTI_Init(EXTI_InitStructure);// 5. 配置NVIC for EXTI0NVIC_InitStructure.NVIC_IRQChannelEXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;// 抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority1;// 响应优先级1NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_Init(NVIC_InitStructure);}// 初始化EXTI2PE2voidEXTI2_Init(void){GPIO_InitTypeDef GPIO_InitStructure;EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;// 1. 使能GPIOE时钟AFIO已经在EXTI0初始化时开启了这里不需要重复开启RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);// 2. 配置PE2为上拉输入GPIO_InitStructure.GPIO_PinGPIO_Pin_2;GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;GPIO_Init(GPIOE,GPIO_InitStructure);// 3. 映射PE2到EXTI2GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);// 4. 配置EXTI2EXTI_InitStructure.EXTI_LineEXTI_Line2;EXTI_InitStructure.EXTI_ModeEXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_TriggerEXTI_Trigger_Falling;// 下降沿触发EXTI_InitStructure.EXTI_LineCmdENABLE;EXTI_Init(EXTI_InitStructure);// 5. 配置NVIC for EXTI2NVIC_InitStructure.NVIC_IRQChannelEXTI2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority2;// 抢占优先级2比EXTI0低NVIC_InitStructure.NVIC_IRQChannelSubPriority0;// 响应优先级0NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_Init(NVIC_InitStructure);}// 如果需要EXTI3、EXTI4依此类推...// 主函数中调用intmain(void){NVIC_Config();// 先设置NVIC分组EXTI0_Init();// 初始化EXTI0EXTI2_Init();// 初始化EXTI2// EXTI3_Init(); // 如果需要while(1){// 主循环}}多个中断的服务函数// EXTI0的中断服务函数对应PA0voidEXTI0_IRQHandler(void){// 检查是否是EXTI0产生的中断if(EXTI_GetITStatus(EXTI_Line0)!RESET){// 处理PA0的中断// 比如LED1翻转GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5)));// 清除中断标志EXTI_ClearITPendingBit(EXTI_Line0);}}// EXTI2的中断服务函数对应PE2voidEXTI2_IRQHandler(void){// 检查是否是EXTI2产生的中断if(EXTI_GetITStatus(EXTI_Line2)!RESET){// 处理PE2的中断// 比如LED2翻转GPIO_WriteBit(GPIOB,GPIO_Pin_6,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_6)));// 清除中断标志EXTI_ClearITPendingBit(EXTI_Line2);}}// EXTI3的中断服务函数如果需要voidEXTI3_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line3)!RESET){// 处理PE3的中断// ...EXTI_ClearITPendingBit(EXTI_Line3);}}// EXTI4的中断服务函数如果需要voidEXTI4_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line4)!RESET){// 处理PE4的中断// ...EXTI_ClearITPendingBit(EXTI_Line4);}}// 注意EXTI5-9共享一个中断服务函数voidEXTI9_5_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line5)!RESET){// 处理线5的中断EXTI_ClearITPendingBit(EXTI_Line5);}if(EXTI_GetITStatus(EXTI_Line6)!RESET){// 处理线6的中断EXTI_ClearITPendingBit(EXTI_Line6);}// ... 直到线9}// EXTI10-15共享一个中断服务函数voidEXTI15_10_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line10)!RESET){// 处理线10的中断EXTI_ClearITPendingBit(EXTI_Line10);}// ... 直到线15}NVIC分组只需要设置一次NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 整个程序只调用一次放在main函数最开头不能在每个中断初始化函数里重复调用每个中断线有自己的配置EXTI0用EXTI_Line0和EXTI0_IRQnEXTI2用EXTI_Line2和EXTI2_IRQn互不干扰共享中断线的处理方式如果你同时用了PE5和PE6它们都会进入EXTI9_5_IRQHandler需要在函数内分别判断voidEXTI9_5_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line5)!RESET){// PE5的处理EXTI_ClearITPendingBit(EXTI_Line5);}if(EXTI_GetITStatus(EXTI_Line6)!RESET){// PE6的处理EXTI_ClearITPendingBit(EXTI_Line6);}}时钟只需要开启一次AFIO时钟在第一个中断初始化时开启即可后面的不需要重复开但每个GPIO的时钟要分别开GPIOA、GPIOE等intmain(void){// 1. 设置NVIC分组只一次NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 2. 开启AFIO时钟只一次RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 3. 分别初始化各个中断EXTI0_Init();// PA0EXTI2_Init();// PE2EXTI3_Init();// PE3EXTI4_Init();// PE4while(1);}// 然后分别实现 EXTI0_IRQHandler、EXTI2_IRQHandler、EXTI3_IRQHandler、EXTI4_IRQHandler
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2420339.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!