尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

STM32学习(六)—— 外部中断

发布时间:2026/9/16 9:09:01

资讯中心
01
ARTICLE

STM32学习(六)—— 外部中断

STM32学习(六)—— 外部中断
一、程序的运行方式1. 轮询系统指的是在程序运行时首先对所有的硬件进行初始化然后在主程序中写一个死循环需要运行的功能按照顺序进行执行轮询系统是一种简单可靠的方式一般适用于在只需要按照顺序执行的并且没有外部时间的影响的情况下。程序的运行过程中出现如按键灯需要外部检测的事件轮询系统的实时响应能力变的很差2. 前后台系统相比于轮询系统前后台系统增加中断的概念如果外部时间发生则在中断中进行处理主程序在轮询系统中运行中断被称为前台主程序的while(1)就称为后台。中断会终止后台程序的运行然后跳转到对应的中断服务函数中去处理处理完成后在继续执行后台的程序。如果使用前后台系统会大大的提高程序的实时响应能力避免造成外部事件的确实。3. 多任务系统相比于前后台系统多任务系统的外部事件也是在中断中进行响应但是外部事件的处理是任务中进行处理。任务具有优先级优先级高的任务先处理所以程序就会被分割为一个个的任务任务是一个独立的死循环并且不能返回可以由操作系统进行任务的调度程序段的实时响应能力又能得到提升。二、外部中断的概念1. 中断的概念中断指的是CPU来处理和响应外部发生的异常中断也就意味着打断比如打断正在做的事然后去处理一个紧急的事处理完成后在继续做刚才没做完的事。比如打游戏女朋友来电话。2. 中断源分析中断源指的是中断发生的源头中断源在内核中已经定义好了也称为向量表向量表参考STM32F4中文参考手册。Cortex-M4内核一共支持256个中断其中16个内核中断240个外部中断只不过对于STM32F407系列来说只用到了一部分包含了10个内核中断不可屏蔽中断无法通过软件进行控制、82个外部中断可屏蔽中断可以通过软件进行控制。对于SMT32的中断异常而言分为两类内核异常外部异常。3.NVIC的概述NVIC指的是嵌套向量中断控制器属于内核中的外设作用是管理所有的中断比如中断的使能或失能、中断的优先级不管是Cortex A系列还是Cortex M系列的内核内部均有NVIC通过NVIC来管理内核异常和外部异常。①。 中断的使能与失能NVIC管理中断通道的打开与关闭可以把NVIC理解为所有中断的开关想要使用中断发送中断请求就必须提前打开中断的通道关于NVIC的使用都存储在一共结构体中这个结构体和NVIC的函数接口都定义在misc.c和misc.h中②. 中断的优先级设置NVIC利用4bit的优先级来管理所有的中断通道STM32中断的优先级分为两种抢占式优先级主优先级响应式优先级次优先级每种都有16个优先级0~15数字越小优先级越高。意义如果同时发生多个中断请求但是又不能同时处理就根据中断强求的优先级来处理和响应中断。抢占优先级主优先级抢占优先级高的中断可以打断抢占优先级低的中断的执行。响应优先级次优先级在同时发生多个中断的情况下抢占优先级相同的情况下响应优先级高的先执行。思考抢占优先级和响应优先级之间的区别(1) 抢占优先级高的中断可以打断抢占优先级低的中断的执行(2) 抢占优先级一样高的中断响应优先级高的中断不可以打断响应优先级低的中断(3)抢占优先级一样高的中断如果同时发生的情况下响应优先级高的先执行(4) 抢占优先级和响应优先级一样高的中断同时发生则按照向量表中的优先级执行为了方便用户管理和响应中断NVIC提供一个函数接口可以对中断优先级进行分组函数原型void NVIC_PriorityGroupConfig(unit32_t NVIC_PriorityGroup)函数参数参数一NVIC_PriorityGroup 打算设置的NVIC优先级分组 一般为NVIC_PriorityGroup_2返回值 None注意设置中断优先级分组应该在主程序运行的开头部分进行并且不能随意修改分组否则会出现中断管理混乱导致程序出现未知问题。int main() { //设置优先级分组 NVIC_PriorityGroutConfig(NVIC_PriorityGrout_2); //对硬件进行初始化 }4. EXTI的概述EXTI指的是外部中断/时间控制器一共有23个每个都有一共内部的边沿检测器可以检测上升沿或者下降沿每根线都可以产生时间或者中断。上升沿指的是电平信号由低变高的那一刻下降沿指的是电平信号由高变低的那一刻想要搞清楚EXTI的使用流程必须看懂EXTI的框图注意每个GPIO引脚都可以配置为外部中断但是和GPIO相关的外部中断线一共有16跟分别为EXTI0~EXTI15。思考STM32F407系列有114个GPIO口那如何和外部中断线进行关联通过映射的方式如果想要让外部中断线和GPIO口进行映射需要使用一个函数接口SYSCFG_EXTILineConfig()函数原型void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, unit8_t EXTI_PinSourcex)函数参数参数一EXTI_PortSourceGPIOx 想要映射的GPIO端口 如EXTI_PortSourceGPIOA参数二EXTI_PinSourcex 想要映射的GPIO引脚 如EXTI_PinSource0注意因为建立映射的时候需要使用系统配置控制器SYSCFG)所以在编写代码的时候必须打开 SYSCFG 外设的时钟挂载在 APB2 总线下 调用 RCC_APB2PeriphClockCmd()函数三、外部中断的代码编写注意所有端口都具有外部中断功能要使用外部中断线必须将端口配置为输入模式想要使用EXTI进行外部事件的检测可以参考stm32f4xx_extic.h源文件中的开头注释部分1. 应该在工程中添加stm32f4xx_exit.c以及stm32f4xx_syscfg.c两个源文件步骤如下2. 打开GPIO外设时钟 SYSCFG外设时钟,GPIO挂载AHB1总线 SYSCFG挂载在APB2总线3. 定义GPIO初始化结构体结构体配置的时候需要把引脚模式配置为输入模式 初始化4. 调用SYSCFG_EXTILineConfig()函数来对外部中断线和GPIO引脚建立映射关系5. 定义EXTI初始化结构体需要配置外部中断线模式、触发方式......) 初始化① EXTI_Line需要使用的外部中断线 参考EXTI_Lines② EXTI_Mode外部中断线的模式(中断 or事件)参考EXTIMode_TypeDef③ EXTI_Trigger边沿检测方式上升沿、下降沿、边沿参考EXTITrigger_TypeDef④ EXTI_LineCmd 外部中断线使能ENABLE br DISABLE初始化EXTI6. 定义NVIC的初始化结构体并进行赋值中断通道.... 初始化① NVIC_IRQChannel需要打开的中断通道 参考 stm32f4xx.h② NVIC_IRQChannelPreemptionPriority 抢占优先级需要根据分组进行填写③ NVIC_IRQChannelSubPriority 响应优先级需要根据分组进行填写④ NVIC_IRQChannelCmd 中断通道的使能ENABLE or DISABLE初始化NVIC7. 编写中断服务函数 中断服务函数的名字必须从启动文件中进行拷贝注意中断服务函数的格式是固定的没有返回值、没有参数 名字也是固定的void EXTI0_IRQHandler(void){//检测是否发生了中断 if( EXTI_GetITStatus(EXTI_Line0) ! RESET)//清除中断标志 EXTI_ClearITPendingBit(EXTI_Line0)}注意中断服务函数是不需要手动调用的并且不要在中断中添加过长的延时时间会导致系统的响应能力降低如果打算处理比较复杂的时间可以在中断中定义一共标志位然后回到主程序中进行处理代码示例#include stm32f4xx.h //#include reg52.h void LED0_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 打开GPIOA外设时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); // 配置PF9引脚 GPIO_InitStructure.GPIO_Mode GPIO_Mode_OUT; // 输出模式 GPIO_InitStructure.GPIO_OType GPIO_OType_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed GPIO_Speed_100MHz; // 输出速率 GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; // 无上下拉 GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; // 引脚编号 GPIO_Init(GPIOF, GPIO_InitStructure); GPIO_SetBits(GPIOF, GPIO_Pin_9); // 默认不亮 } void EXTI0_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 打开GPIOA外设时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 打开SYSCFG外设时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // 配置PA0引脚 GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN; // 输入模式 GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_NOPULL; // 无上下拉 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // 引脚编号 GPIO_Init(GPIOA, GPIO_InitStructure); // GPIO引脚和外部中断线建立映射关系 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); // 配置外部中断线 EXTI_InitStructure.EXTI_Line EXTI_Line0; // 外部中断线0 EXTI_InitStructure.EXTI_Mode EXTI_Mode_Interrupt; // 中断模式 EXTI_InitStructure.EXTI_Trigger EXTI_Trigger_Falling; // 下降沿触发 EXTI_InitStructure.EXTI_LineCmd ENABLE; // 使能外部中断线0 EXTI_Init(EXTI_InitStructure); // 配置中断优先级 NVIC_InitStructure.NVIC_IRQChannel EXTI_Line0; // 中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0x0F;// 抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority 0x0F; // 响应优先级 NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; // 使能通道 NVIC_Init(NVIC_InitStructure); } int main() { // 1.硬件初始化 LED0_Init(); EXTI0_Init(); // 2.进入死循环 while(1) { } } // 中断服务函数 不需要手动调用 尽量精简 尽量不要添加很长的延时 void EXTI0_IRQHandler(void) { // 检测中断线的标志 if(EXTI_GetITStatus(EXTI_Line0) ! RESET) { GPIO_ToggleBits(GPIOF, GPIO_Pin_9); // 电平翻转 // 清除中断标志位 EXTI_ClearITPendingBit(EXTI_Line0); } }
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。