stm32 外部中断详细讲解 (转)
stm32g030外部中断回调函数
![stm32g030外部中断回调函数](https://img.taocdn.com/s3/m/fab38837f342336c1eb91a37f111f18583d00cb1.png)
一、STM32G030外部中断简介1.1 STM32G030外部中断的定义1.2 STM32G030外部中断的原理1.3 STM32G030外部中断的应用场景二、外部中断回调函数的概念和作用2.1 外部中断回调函数的定义2.2 外部中断回调函数的原理2.3 外部中断回调函数的作用三、STM32G030外部中断回调函数的编写步骤3.1 配置外部中断引脚3.2 初始化外部中断3.3 编写回调函数3.4 注册回调函数3.5 案例演示四、外部中断回调函数的注意事项和常见问题4.1 中断优先级设置4.2 中断清除标志位4.3 嵌套中断处理4.4 延时处理问题五、总结和展望5.1 对STM32G030外部中断回调函数的总结5.2 未来发展趋势和技术应用文章正文:一、STM32G030外部中断简介1.1 STM32G030外部中断的定义STM32G030外部中断是指通过外部引脚(通常为GPIO引脚)来触发微控制器的中断请求,从而实现对外部事件的实时响应。
1.2 STM32G030外部中断的原理STM32G030外部中断的原理是通过设置外部中断触发条件和相应的中断优先级,在外部事件触发时,将中断请求发送给中断控制器,由中断控制器将控制权交给中断服务程序,从而实现对外部事件的处理。
1.3 STM32G030外部中断的应用场景STM32G030外部中断广泛应用于各种外部事件的处理,例如按钮按下、传感器检测等实时事件的响应和处理。
二、外部中断回调函数的概念和作用2.1 外部中断回调函数的定义外部中断回调函数是指在外部中断事件触发时自动执行的函数,通常由用户在程序中编写并注册,用于处理外部中断事件。
2.2 外部中断回调函数的原理外部中断回调函数的原理是通过在中断服务程序中调用注册的回调函数来处理外部中断事件,从而实现针对性的事件响应和处理。
2.3 外部中断回调函数的作用外部中断回调函数的作用是实现对外部中断事件的定制化处理,提高系统的灵活性和可维护性。
stm32外部中断实验报告-STM32实例外部中断实验
![stm32外部中断实验报告-STM32实例外部中断实验](https://img.taocdn.com/s3/m/a674512bdcccda38376baf1ffc4ffe473368fdf2.png)
stm32外部中断实验报告_STM32实例外部中断实验上⼀篇⽂章我们介绍了 STM32F10x 的中断,这次我们就来学习下外部中断。
本⽂中要实现的功能与按键实验⼀样,即通过按键控制LED,只不过这⾥采⽤外部中断⽅式进⾏控制。
学习时可以参考《STM32F10x 中⽂参考⼿册》-9 中断和事件章节。
外部中断介绍EXTI 简介STM32F10x 外部中断/事件控制器(EXTI)包含多达 20 个⽤于产⽣事件/中断请求的边沿检测器。
EXTI 的每根输⼊线都可单独进⾏配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发),还可独⽴地被屏蔽。
EXTI 结构框图EXTI 框图包含了 EXTI 最核⼼内容,掌握了此框图,对 EXTI 就有⼀个全局的把握,在编程的时候思路就⾮常清晰。
从图中可以看到,有很多信号线上都有标号 9 样的“20”字样,这个表⽰在控制器内部类似的信号线路有 20 个,这与 STM32F10x 的 EXTI 总共有20 个中断/事件线是吻合的。
因此我们只需要理解其中⼀个的原理,其他的 19个线路原理都是⼀样的。
EXTI 分为两⼤部分功能,⼀个产⽣中断,另⼀个产⽣事件,这两个功能从硬件上就有所差别,这个在框图中也有体现。
从图中标号 3 的位置处就分出了两条线路,⼀条是 3-4-5 ⽤于产⽣中断,另⼀条是 3-6-7-8⽤于产⽣事件。
下⾯我们就来介绍下这两条线路:(1)⾸先看下产⽣中断的这条线路(1-2-3-4-5)1.标号 1 为输⼊线,EXTI 控制器有 20 个中断/事件输⼊线,这些输⼊线可以通过寄存器设置为任意⼀个 GPIO,也可以是⼀些外设的事件,这部分内容我们会在后⾯专门讲解。
输⼊线⼀般是存在电平变化的信号。
2.边沿检测电路,EXTI 可以对触发⽅式进⾏选择,通过上升沿触发选择寄存器和下降沿触发选择寄存器对应位的设置来控制信号触发。
边沿检测电路以输⼊线作为信号输⼊端,如果检测到有边沿跳变就输出有效信号 1 给红⾊框 3 电路,否则输出⽆效信号 0。
STM32外部中断处理流程
![STM32外部中断处理流程](https://img.taocdn.com/s3/m/d34f715dc381e53a580216fc700abb68a982ad0e.png)
STM32外部中断处理流程外部中断是指引发中断的事件来自于MCU外部的输入引脚或外设,需要通过配置寄存器和中断服务程序来处理外部中断。
在STM32系列MCU中,外部中断处理可分为以下几个步骤。
1.配置中断引脚要使用外部中断功能,首先需要配置中断引脚。
对于STM32,外部中断引脚由GPIO口提供,需要通过GPIO配置寄存器设置相关引脚的工作模式、上下拉和中断触发方式等。
具体配置方法可以参考芯片手册。
2.配置中断控制器外部中断的中断源需要连接到中断控制器(NVIC),通过配置NVIC的相关寄存器来使能外部中断。
NVIC是位于ARM Cortex-M内核内部的外设,用于管理和分配中断优先级。
3.编写中断服务程序(ISR)中断服务程序(Interrupt Service Routine, ISR)是用于处理中断事件的函数,当外部中断引发时,MCU会跳转到相应的ISR进行处理。
在编写ISR时,需要注意以下几点:-确定中断源:可以通过读取中断状态寄存器来判断是哪个外部中断引起的中断。
-处理中断事件:根据中断源的不同,进行相应的处理。
例如,可以读取输入引脚状态、处理外设状态等。
-清除中断标志位:要在ISR内部清除中断标志位,以允许MCU再次响应该外部中断。
具体方法是通过读取相应的寄存器或调用相关函数清除中断标志位。
4.配置中断优先级中断优先级用于确定ISR的响应顺序,优先级较高的中断先被处理。
在STM32中,中断优先级可以通过配置中断控制器的相关寄存器进行设置。
5.启用中断在完成上述步骤后,需要启用相应的中断引脚和中断控制器。
具体方法是通过设置GPIO寄存器来使能中断引脚,并通过设置NVIC寄存器来使能相关中断。
6.处理中断请求一旦发生外部中断事件,MCU就会跳转到相应的ISR进行中断处理。
在ISR中,可以根据需要调用其他的函数或执行其他的操作。
处理完成后,可以通过清除中断标志位和退出中断函数来结束中断处理。
STM32F103学习笔记(五) 外部中断
![STM32F103学习笔记(五) 外部中断](https://img.taocdn.com/s3/m/c4de1201650e52ea551898bb.png)
STM32F103学习笔记(五)外部中断首先是外部中断基本的概念:STM32 的每个IO 都可以作为外部中断的中断输入口,这点也是STM32 的强大之处。
STM32F103 的中断控制器支持19 个外部中断/事件请求。
每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F103 的19 个外部中断为:线0~15:对应外部IO 口的输入中断。
线16:连接到PVD 输出。
线17:连接到RTC 闹钟事件。
线18:连接到USB 唤醒事件。
线16~18还没有学到只看了线0~15。
每个中断线对应着7个GPIO口,形成映射关系,以线0 为例:它对应了GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0。
而中断线每次只能连接到1 个IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个GPIO 上了。
下面我们看看GPIO 跟中断线的映射关系图:根据映射关系,就开始配置按键对应GPIO口和中断的映射了:[csharp] view plain copy <pre name="code" class="csharp"><prename="code" class="html">void EXTIX_Init(void){ EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; KEY_Init(); // 按键端口初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,EN ABLE); //使能复用功能时钟//GPIOE.2 中断线以及中断初始化配置下降沿触发GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_Pi nSource2);EXTI_InitStructure.EXTI_Line=EXTI_Line2; //KEY2 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOE.3 中断线以及中断初始化配置下降沿触发//KEY1GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_Pi nSource3);EXTI_InitStructure.EXTI_Line=EXTI_Line3;EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOE.4 中断线以及中断初始化配置下降沿触发//KEY0GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_Pi nSource4);EXTI_InitStructure.EXTI_Line=EXTI_Line4;EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器//GPIOA.0 中断线以及中断初始化配置上升沿触发PA0 WK_UPGPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_Pi nSource0);EXTI_InitStructure.EXTI_Line=EXTI_Line0;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//使能按键WK_UP所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//使能按键KEY2所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//使能按键KEY1所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//使能按键KEY0所在的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器} //外部中断0服务程序voidEXTI0_IRQHandler(void) { delay_ms(10);//消抖if(KEY3==1) //WK_UP按键{ BEEP=!BEEP; } EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位} //外部中断2服务程序voidEXTI2_IRQHandler(void) { delay_ms(10);//消抖if(KEY2==0) //按键KEY2{ LED0=!LED0; }EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE2上的中断标志位} //外部中断3服务程序voidEXTI3_IRQHandler(void) { delay_ms(10);//消抖if(KEY1==0) //按键KEY1{ LED1=!LED1; }EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位} void EXTI4_IRQHandler(void){ delay_ms(10);//消抖if(KEY0==0) //按键KEY0 { LED0=!LED0;LED1=!LED1; }EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志位} [html] view plain copy。
stm32f103c8t6外部中断原理
![stm32f103c8t6外部中断原理](https://img.taocdn.com/s3/m/4a4764f164ce0508763231126edb6f1aff0071d5.png)
一、概述在嵌入式系统中,外部中断是一种常见的事件触发机制,它能够使处理器在执行程序的过程中,及时地响应外部事件的发生,从而提高系统的实时性和稳定性。
在基于STM32F103C8T6芯片的嵌入式系统开发中,外部中断的使用具有重要的意义。
本文将介绍STM32F103C8T6外部中断的原理及其应用。
二、STM32F103C8T6外部中断的原理1. 外部中断概述外部中断是指处理器接收到外部输入信号后,及时地中断当前的程序执行,转而执行事先定义好的中断服务程序。
在STM32F103C8T6芯片中,具有多个外部中断引脚以及相关的中断控制寄存器,可以方便地实现外部中断功能。
2. 中断控制器STM32F103C8T6芯片的中断控制器包含若干中断控制寄存器,用于配置外部中断的触发条件、优先级、使能状态等。
通过对中断控制寄存器的配置,可以灵活地控制外部中断的响应行为。
3. NVICSTM32F103C8T6芯片内部集成了Nested Vectored Interrupt Controller(NVIC),负责管理和调度所有的中断源。
在实现外部中断功能时,需要通过NVIC对外部中断源进行优先级和使能的设置。
4. 外部中断触发条件在STM32F103C8T6芯片中,外部中断可以以上升沿、下降沿、上升沿和下降沿、低电平或者高电平触发。
在配置外部中断时,需要根据实际应用需求选择合适的触发条件,并进行相应的配置。
5. 外部中断服务程序一旦外部中断触发条件满足,处理器将立即响应中断,并跳转到预先定义好的外部中断服务程序中执行。
外部中断服务程序通常用于处理外部事件的逻辑,例如状态更新、数据采集、报警处理等。
三、STM32F103C8T6外部中断的应用1. 外部按键控制在很多嵌入式系统中,外部按键常常作为用户与系统交互的途径。
通过STM32F103C8T6的外部中断功能,可以轻松地实现外部按键的检测和响应,从而实现用户界面的交互控制。
STM32中断程序(带详细注释)
![STM32中断程序(带详细注释)](https://img.taocdn.com/s3/m/4112035f4b35eefdc9d33338.png)
本文档免费下载,如果你觉得对你有帮助,情给好评并下载,我需要财富值,谢谢!/**********************STM32F103外部中断*********************************************长沙理工大学3+1实验室**********************************************2012年9月22日*************************/#include"stm32f10x.h"//配置系统时钟************************************************************void RCC_Configuration(void){ErrorStatus HSEStartUpStatus; //将外部时钟设置成枚举变量RCC_DeInit(); //复位RCC外部设备寄存器到默认值RCC_HSEConfig(RCC_HSE_ON); //打开外部时钟HSEStartUpStatus=RCC_WaitForHSEStartUp(); //检测外部时钟是否就绪if(HSEStartUpStatus==SUCCESS) //如果就绪(SUCCESS)则进行下一步程序{FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启flash缓冲功能(使能缓存)FLASH_SetLatency(FLASH_Latency_2); //延时两个周期RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置AHB时钟为不分频的系统时钟RCC_PCLK1Config(RCC_HCLK_Div2); //设置AP1为2分频系统时钟(不能超过36M)RCC_PCLK2Config(RCC_HCLK_Div1); //设置AP1为为系统时钟频率(前面AHB给定的时钟)RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); //设置外部时钟为PLL的上输入时钟并且倍频9RCC_PLLCmd(ENABLE); //使能PLL时钟while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET) //检测PLL是否就绪RESET:就绪{}RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //配置外部时钟作为系统的时钟while(RCC_GetSYSCLKSource()!=0x08) //检测外部时钟是否作为PLL的输入时钟{}}}//配置GPIO函数************************************************//功能:配置GPIO的输入输出模式void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化函数RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE); //使能GPIOA和GPIOB的时钟,配置其复用模式//配置GPIO口的输入*******GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; //配置1脚为输入脚GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //配置GPIO为上拉输入模式GPIO_Init(GPIOA,&GPIO_InitStructure); //把配置好的GPIO口初始化一下// 配置GPIO的输出*******GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3); //将PA2和PA3拉高GPIO_SetBits(GPIOB,GPIO_Pin_2); //将PA2和PA3拉高GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //配置0脚为输出脚GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 配置GPIO为推挽输出模式GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //配置GPIO口的输出速率是50MGPIO_Init(GPIOA,&GPIO_InitStructure); //使能GPIOA口}//外部中断函数*************************************************************************************void EXTI_Configuration(void){EXTI_InitTypeDef EXTI_InitStructure; //初始化外部中断寄存器RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能IO时钟EXTI_ClearITPendingBit(EXTI_Line1); //清除IO口中断清除挂起位(清除中断标志位)EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt; //设置外部中断触发(另一种是事件触发)EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //设置中断触发方式:上下沿触发方式EXTI_InitStructure.EXTI_Line=EXTI_Line1; //选择中断线路为1(即选择那个IO作为中断输入)EXTI_InitStructure.EXTI_LineCmd=ENABLE; //使能外部中断EXTI_Init(&EXTI_InitStructure); //初始化GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1); //将GPIOA1挂到中断上}//中断分组函数***************************************************************void NIVC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure; //初始化中断分组函数//NVIC_PriorityGroupConfig:设置优先级分组(下面一句)NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //设置抢占式优先级:先占优先级0位,从优先级4位NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn; //将中断挂到GPIO1脚外部中断线1上NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; //设置响应式优先级:先占优先级1位,从先级3位NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; // 使能设置的外部中断通道请求NVIC_Init(&NVIC_InitStructure); //初始化}//中断服务函数********************************************************void EXTI1_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line1)!=RESET){//添加中断处理函数GPIO_ResetBits(GPIOA,GPIO_Pin_2); //点亮ledEXTI_ClearFlag(EXTI_Line1); //清除标志中断位EXTI_ClearITPendingBit(EXTI_Line1); //清除外部中断线1的挂起位}}//主函数***********************************************************************int main(void){RCC_Configuration(); //调用系统时钟函数GPIO_Configuration(); //调用GPIONIVC_Configuration();EXTI_Configuration();while(1);}Welcome To Download !!!欢迎您的下载,资料仅供参考!。
stm32外部中断实验原理
![stm32外部中断实验原理](https://img.taocdn.com/s3/m/ab075c2349d7c1c708a1284ac850ad02de8007f8.png)
stm32外部中断实验原理STM32是一款高性能32位微控制器系列,其外部中断功能能实现对外部事件的监听和响应。
在实验中,外部中断功能可用于监测外部输入信号的变化,并触发相应的处理操作。
下面我们将详细介绍STM32外部中断实验的原理。
首先,我们需要了解STM32的外部中断引脚和中断控制器的结构。
STM32的每个GPIO引脚都可以用作外部中断输入,中断控制器负责监听和响应外部中断信号。
中断控制器包括中断请求线(IRQ)、中断优先级控制、中断屏蔽和中断处理等功能。
在STM32外部中断实验中,首先需要将待检测的信号连接到GPIO引脚上。
然后,通过对GPIO的配置,将其设置为输入模式,并启用外部中断功能。
同时,还需要配置中断优先级和触发条件。
在配置GPIO引脚时,首先需要选择合适的GPIO引脚和对应的GPIO端口。
然后,通过修改GPIO的控制寄存器,将其设置为输入模式。
接下来,还需要配置GPIO的中断触发方式,可选择边沿触发(上升沿、下降沿)或电平触发(低电平、高电平)。
这取决于外部信号的特性和应用需求。
配置外部中断功能后,接下来需要配置中断控制器。
首先,需要使能中断控制器的相应外部中断通道。
然后,通过设置优先级控制寄存器,设置外部中断的优先级。
中断优先级决定了中断处理的优先级顺序,一个高优先级的中断将在低优先级中断结束后立即执行。
在外部中断触发时,中断控制器会通过中断请求线(IRQ)将中断请求发送给CPU。
CPU在处理完当前指令后,会进入中断服务程序(ISR)进行中断处理。
中断服务程序是根据中断号进行编号的,中断触发时,CPU会跳转到对应的中断服务程序进行处理。
在中断服务程序中,可以进行一系列的处理操作,如读取外部输入信号、更新相关变量或执行特定的操作。
在STM32外部中断实验中,我们可以实现一些功能,如按键检测、触摸检测、传感器检测等。
通过配置外部中断功能,我们可以实时地检测外部输入信号的变化,并触发相应的处理操作。
STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)
![STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)](https://img.taocdn.com/s3/m/fcfd68e1b1717fd5360cba1aa8114431b90d8e15.png)
STM32CubeMX实战教程(三)——外部中断(中断及HAL_Delay函数避坑)在STM32CubeMX实战教程中,我们已经学习了如何使用GPIO来控制LED的亮灭。
在这篇文章中,我们将进一步学习如何使用外部中断来实现更复杂的功能。
外部中断可以使我们的微控制器能够在输入发生变化时立即做出响应。
这对于需要实时性的应用非常重要,比如按钮的按下或松开的检测。
外部中断类似于计数器,不断地检测输入引脚的变化,并在变化时触发中断。
在STM32CubeMX中配置外部中断非常简单。
我们只需要选择外部输入引脚作为中断源,然后为中断配置触发方式即可。
触发方式可以是上升沿、下降沿或双边沿触发。
但要注意的是,当使用外部中断时,我们应该避免在中断服务子程序(ISR)中使用延时函数,如HAL_Delay。
这是因为在ISR中调用延时函数会导致中断响应时间增加,从而影响其他中断的响应和整个系统的实时性。
所以在ISR中,我们只能执行最核心、最迅速的操作。
为了避免在ISR中使用延时函数,我们可以使用定时器中断来实现延时。
定时器中断是一种定期触发的中断,在ISR中我们可以通过判断定时器的计数值来实现一定时间的延时。
下面是一个使用外部中断的示例代码:```c#include "stm32f4xx_hal.h"GPIO_InitTypeDef GPIO_InitStruct;EXTI_HandleTypeDef hexti;void SysTick_Handler(void)HAL_IncTick(;HAL_SYSTICK_IRQHandler(;void EXTI_IRQHandler(void)HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //在这里执行最核心、最迅速的操作int main(void)HAL_Init(;SystemClock_Config(;__HAL_RCC_GPIOA_CLK_ENABLE(;__HAL_RCC_SYSCFG_CLK_ENABLE(;GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_PULLDOWN;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);HAL_NVIC_EnableIRQ(EXTI0_IRQn);while (1)//在这里执行其他操作}```在这个示例中,我们使用PA0引脚,即用户按钮作为外部中断源。
STM32外部中断5-9,10-15的应用解析
![STM32外部中断5-9,10-15的应用解析](https://img.taocdn.com/s3/m/fde59be7f705cc1755270949.png)
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//配置
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource9);//PE9连接到中断线9
/*配置EXTI_Line5 */
EXTI_InitStructure.EXTI_Line = EXTI_Line5;//LINE5
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
EXTI_InitStructure.EXTI_Trigger =EXTI_Trigger_Rising; //上升沿触发
STM32外部中断5-9,10-15的应用解析
STM32有些系列(比如STM32F407)的外部中断5-9是共用一个中断处理函数EXTI9_5_IRQHandler(),外部中断10-15共用中断函数EXTI15_10_IRQHandler(),所以很多人(包括我自己)刚开始时对于这些外部中断线的设置以及判断都不是弄得很清楚,下面就直接贴出中断引脚的配置、中断配置以及进入中断之后的判断处理程序。
STM32外部中断原理与配置
![STM32外部中断原理与配置](https://img.taocdn.com/s3/m/41fbe8761fd9ad51f01dc281e53a580216fc508c.png)
STM32外部中断原理与配置STM32-外部中断原理与配置IO⼝外部中断原理概述STM32控制器⽀持的外部中断/事件请求中断线M3M4M7EXTI线0~15:对应外部IO⼝的输⼊中断。
√√√EXTI线16:连接到PVD输出。
√√√EXTI线17:连接到RTC闹钟事件。
√√√EXTI线18:连接到USB OTG FS唤醒事件。
√√√EXTI线19:连接到以太⽹唤醒事件。
√√EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件√√EXTI线21:连接到RTC⼊侵和时间戳事件。
√√EXTI线22:连接到RTC唤醒事件。
√√EXSTI线23:连接到LPTIM1异步事件√IO⼝外部中断STM32的每个IO都可以作为外部中断输⼊。
每个外部中断线可以独⽴的配置触发⽅式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专⽤的状态位。
STM32供IO使⽤的中断线只有16个,但是STM32F系列的IO⼝多达上百个,STM32F103ZGT6(112),那么中断线怎么跟io⼝对应呢?GPIO和中断线映射关系GPIOx.0映射到EXTI0GPIOx.1映射到EXTI1……GPIOx.14映射到EXTI14GPIOx.15映射到EXTI15对于M4/M7,配置寄存器为SYSCFG_EXTIRx对于M3,配置寄存器为AFIO_EXTICRx如下图所⽰,EXTI0[3:0]有4个位,可以配置16个,所以可以从PA0选择到PI0。
也就是说16个中断线,最多可以处理16*16个外部引脚的中断。
可以在⼿册中找到SYSCFG 外部中断配置寄存器:16个中断线就分配16个中断服务函数?IO⼝外部中断在中断向量表中只分配了7个中断向量,也就是只能使⽤7个中断服务函数。
从表中可以看出,外部中断线5~ 9分配⼀个中断向量,共⽤⼀个服务函数外部中断线10~15分配⼀个中断向量,共⽤⼀个中断服务函数。
中断服务函数列表:EXTI0_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerEXTI9_5_IRQHandlerEXTI15_10_IRQHandlerIO⼝外部中断HAL库配置⽅法外部中断操作使⽤到的函数分布⽂件stm32fxxx_hal_gpio.hstm32fxxx_hal_gpio.c外部中断配置:外部中断的中断线映射配置和触发⽅式都是在GPIO初始化函数中完成:GPIO_InitTypeDef GPIO_Initure;GPIO_Initure.Pin=GPIO_PIN_0; //PA0GPIO_Initure.Mode=GPIO_MODE_IT_RISING; //上升沿触发GPIO_Initure.Pull=GPIO_PULLDOWN;HAL_GPIO_Init(GPIOA,&GPIO_Initure);void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init){uint32_t position;uint32_t ioposition = 0x00;uint32_t iocurrent = 0x00;uint32_t temp = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Init->Pin));assert_param(IS_GPIO_MODE(GPIO_Init->Mode));assert_param(IS_GPIO_PULL(GPIO_Init->Pull));/* Configure the port pins */for(position = 0; position < GPIO_NUMBER; position++){/* Get the IO position */ioposition = ((uint32_t)0x01) << position;/* Get the current IO position */iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;if(iocurrent == ioposition){/*--------------------- GPIO Mode Configuration ------------------------*//* In case of Alternate function mode selection */if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)){/* Check the Alternate function parameter */assert_param(IS_GPIO_AF(GPIO_Init->Alternate));/* Configure Alternate function mapped with the current IO */temp = GPIOx->AFR[position >> 3];temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));GPIOx->AFR[position >> 3] = temp;}/* Configure IO Direction mode (Input, Output, Alternate or Analog) */temp = GPIOx->MODER;temp &= ~(GPIO_MODER_MODER0 << (position * 2));temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));GPIOx->MODER = temp;/* In case of Output or Alternate function mode selection */if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD)) {/* Check the Speed parameter */assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));/* Configure the IO Speed */temp = GPIOx->OSPEEDR;temp &= ~(GPIO_OSPEEDER_OSPEEDR0 << (position * 2));temp |= (GPIO_Init->Speed << (position * 2));GPIOx->OSPEEDR = temp;/* Configure the IO Output Type */temp = GPIOx->OTYPER;temp &= ~(GPIO_OTYPER_OT_0 << position) ;temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);GPIOx->OTYPER = temp;}/* Activate the Pull-up or Pull down resistor for the current IO */temp = GPIOx->PUPDR;temp &= ~(GPIO_PUPDR_PUPDR0 << (position * 2));temp |= ((GPIO_Init->Pull) << (position * 2));GPIOx->PUPDR = temp;/*--------------------- EXTI Mode Configuration ------------------------*//* Configure the External Interrupt or event for the current IO */if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE){/* Enable SYSCFG Clock */__HAL_RCC_SYSCFG_CLK_ENABLE();temp = SYSCFG->EXTICR[position >> 2];temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));temp |= ((uint32_t)(GPIO_GET_INDEX(GPIOx)) << (4 * (position & 0x03)));SYSCFG->EXTICR[position >> 2] = temp;/* Clear EXTI line configuration */temp = EXTI->IMR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT){temp |= iocurrent;}EXTI->IMR = temp;temp = EXTI->EMR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT){temp |= iocurrent;}EXTI->EMR = temp;/* Clear Rising Falling edge configuration */temp = EXTI->RTSR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE){temp |= iocurrent;}EXTI->RTSR = temp;temp = EXTI->FTSR;temp &= ~((uint32_t)iocurrent);if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE){temp |= iocurrent;}EXTI->FTSR = temp;}}}}和串⼝中断⼀样,HAL库同样提供了外部中断通⽤处理函数HAL_GPIO_EXTI_IRQHandler,我们在外部中断服务函数中会调⽤该函数处理中断。
stm32中断(NVIC与EXTI)
![stm32中断(NVIC与EXTI)](https://img.taocdn.com/s3/m/9820ccd6581b6bd97e19eaaf.png)
stm32中断(NVIC与EXTI) D部有4个从优先级(00 01 10 11)。
1.中断输入与悬起当中断输入脚被置为有效后,该中断就被“悬起”。
所谓“悬起”,也就是等待、就绪的意思。
即使后来中断源撤消了中断请求,已经被标记成悬起的中断也被记录下来。
当某中断的服务程序开始执行时,就称此中断进入了“活跃”状态,并且其悬起位会被硬件自动清除。
在一个中断活跃后,直到其服务例程执行完毕,并且返回后,才能对该中断的新请求予以响应。
当NVIC响应一个中断时,会自动完成以下三项工作,以便安全、准确地跳转到相应的中断服务程序:入栈:把8个寄存器的值压入栈。
当响应中断时,如果当前的代码正在使用PSP,则压入PSP(进程堆栈),否则就压入MSP(主堆栈)。
一旦进入了服务例程,就一直使用主堆栈。
在自动入栈的过程中,将寄存器写入堆栈的顺序与时间顺序无关,CM3会保证正确的寄存器被保存到正确的位置。
取向量:当数据总线(系统总线)进行入栈操作时,指令总线(I-Code总线)正在从向量表中找出正确的中断向量与对应的服务程序入口地址。
更新寄存器。
注意:①如果在某个中断得到响应之前,其悬起状态被清除了,则中断被取消。
②新请求在得到响应时,由硬件自动清零其悬起标志位。
③如果中断源咬住请求信号不放,该中断就会在其上次服务例程返回后再次被置为悬起状态。
④如果某个中断在得到响应之前,其请求信号以若干的脉冲的方式呈现,则被视为只有一次中断请求⑤如果在服务例程执行时,中断请求释放了,但是在服务例程返回前又重新被置为有效,则NVIC会记住此动作,重新悬起该中断。
2.中断返回当中断完成,返回主程序时,NVIC自动完成以下两步:①出栈:先前压入栈中的寄存器在这里恢复。
内部的出栈顺序与入栈时的相对应,堆栈指针的值也改回先前的值。
②更新NVIC 寄存器:伴随着中断的返回,它的活动位也被硬件清除。
对于外部中断,倘若中断输入再次被置为有效,则悬起位也将再次置位,新一次的中断响应序列也会再次开始。
(stm32f103学习总结)—stm32外部中断
![(stm32f103学习总结)—stm32外部中断](https://img.taocdn.com/s3/m/1a4852305627a5e9856a561252d380eb62942342.png)
(stm32f103学习总结)—stm32外部中断⼀、外部中断介绍1.1 EXTI简介 EXTI简介 STM32F10x外部中断/事件控制器(EXTI)包含多达 20 个⽤于产⽣事 件/中断请求的边沿检测器。
EXTI的每根输⼊线都可单独进⾏配置,以选 择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或 边沿触发),还可独⽴地被屏蔽。
(stm32f103有19个)1.2 EXTI结构框图1.3 外部中断/事件线映射 STM32F10x的EXTI具有20个中断/事件线,如下:(stm32f103有19个以太⽹唤醒事件没有;stm32f107有20个) STM32F10x 的 EXTI 供外部 IO ⼝使⽤的中断线有 16 根,但是我们使⽤的 STM32F103 芯⽚却远远不⽌ 16 个 IO ⼝,那么 STM32F103 芯⽚怎么解决这个问题的呢? 因为 STM32F103 芯⽚每个 GPIO 端⼝均有 16 个管脚,因此把每个端⼝的 16 个 IO 对应那 16 根中断线 EXTI0-EXTI15 。
⽐如:GPIOx.0-GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 EXTI0-EXTI15,这样⼀来每个中断线就对应了最多 7 个 IO ⼝,⽐如:GPIOA.0、GPIOB.0、GPIOC.0、GPIOD.0、GPIOE.0、GPIOF.0、GPIOG.0。
但是中断线每次只能连接⼀个在 IO ⼝上,这样就需要通过 AFIO 的外部中断配置寄存器 1 的 EXTIx[3:0]位来决定对应的中断线映射到哪个GPIO 端⼝上,对于中断线映射到 GPIO 端⼝上的配置函数在stm32f10x_gpio.c 和 stm32f10x_gpio.h 中,所以使⽤到外部中断时要把这个⽂件加⼊到⼯程中,在创建库函数模板的时候我们默认已经添加。
EXTI 的 GPIO 映射图如图 18.1.3 所⽰:⼆、外部中断配置步骤 要使⽤外部中断我们就需要先配置它,通常都需经过这⼏步:(1)使能IO ⼝时钟,配置IO ⼝模式为输⼊(2)开启 AFIO 时钟,设置 IO ⼝与中断线的映射关系RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO 时钟void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); //设置IO ⼝与中断线的映射关系即哪个io ⼝哪⼀个管脚作为中断输⼊线GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //这⾥以配置GPIOA ⼝ GPIOA 的第0管脚作为中断输⼊线(3)配置中断分组(NVIC ),使能中断(4)初始化EXTI ,选择触发⽅式(5)编写EXTI 中断服务函数(中断函数固件库中已经定义必须使⽤下列函数名不能⾃⼰定义)EXTI0_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerEXTI9_5_IRQHandlerEXTI15_10_IRQHandler三、编写外部中断控制程序 要实现外部中断⽅式控制LED ,程序框架如下:(1)初始化对应端⼝的EXTI (第三部分中的1-4⼩步)1 void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);2 typedef struct3 {4 uint32_t EXTI_Line; //中断/事件线5 EXTIMode_TypeDef EXTI_Mode; //EXTI 模式6 EXTITrigger_TypeDef EXTI_Trigger; //EXTI 触发⽅式7 FunctionalState EXTI_LineCmd; //中断线使能或失能8 }EXTI_InitTypeDef ;(2)编写EXTI中断函数(3)编写主函数1/*******************************************************************************2* 函数名 : My_EXTI_Init3* 函数功能 : 外部中断初始化4* 输⼊ : ⽆5* 输出 : ⽆6*******************************************************************************/7void My_EXTI_Init(void)8{9 NVIC_InitTypeDef NVIC_InitStructure;10 EXTI_InitTypeDef EXTI_InitStructure;1112 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //AFIO使能13 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//选择GPIO管脚⽤作外部中断线路14//EXTI0 NVIC 配置15 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//EXTI0中断通道16 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级17 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //⼦优先级18 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能19 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器20//初始化EXTI 配置21 EXTI_InitStructure.EXTI_Line=EXTI_Line0;22 EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;23 EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;24 EXTI_InitStructure.EXTI_LineCmd=ENABLE;25 EXTI_Init(&EXTI_InitStructure);26}1/*******************************************************************************2* 函数名 : EXTI0_IRQHandler3* 函数功能 : 外部中断0函数4* 输⼊ : ⽆5* 输出 : ⽆6*******************************************************************************/7void EXTI0_IRQHandler(void)8{9 if(EXTI_GetITStatus(EXTI_Line3)==1) //判断EXTI中断标志位状态函数10 {11 //填写中断中需要完成的程序12 }13 EXTI_ClearITPendingBit(EXTI_Line3); //在结束中断服务函数前,清楚中断标志位1415 }。
STM32外部中断(实现按键控制LED)
![STM32外部中断(实现按键控制LED)](https://img.taocdn.com/s3/m/21e97ef0f605cc1755270722192e453610665b16.png)
STM32外部中断(实现按键控制LED)引⾔“中断” 这个概念,指的是在单⽚机运⾏过程中,在指定条件发⽣时,停下当前所有⼯作,去执⾏中断处理函数内的内容。
就像我们在教室上课时,突然地震了,不出意外的话我们都需要停下⼿中学习任务,去进⾏⼀系列的避险动作。
这⼀节我们通过中断的⽅式,完成通过按键控制LED亮灭的操作。
准备环节中断相关知识STM32的中断控制器⽀持19个外部中断/事件请求。
这⼗九个外部中断为:线0~15:对应外部IO⼝的输⼊中断。
线16:连接到PVD输出。
线17:连接到连接到RTC时钟事件。
线18:连接到USB唤醒事件。
配置使⽤时,需要先将IO⼝与相应中断线的映射关系建⽴,再对其进⾏使⽤。
那映射关系是怎样的呢?GPIOx.0 ~ GPIOx.15(x = A,B,C,D,E,F,G)分别对应中断线0 ~ 15配置GPIO与中断线关系的函数是void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)eg:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);把GPIO作为EXTI外部中断时,需要打开AFIO时钟。
APIO时钟何时需要打开,具体可以参考这篇⽂章:嵌套向量中断控制器(NVIC)初始化完线上中断和中断条件等内容,还需要配置中断分组。
配置中断分组之前,我们需要先确定如何进⾏分组。
这⾥就需要⽤到NVIC。
关于NVIC的具体内容可查看这篇博⽂:。
编码环节步骤初始化IO⼝输⼊开启AFIO时钟设置IO⼝与中断线的映射关系初始化线上中断、设置触发条件等配置中断分组,并使能中断编写中断服务函数main.c(以下内容均省略头⽂件)int main(void){delay_init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC终端分组2LED_Init();KEY_Init();EXTIX_Init(); //外部中断初始化LED1 = 0;}exti.h#ifndef __EXTI_H#define __EXIT_H#include "sys.h"void EXTIX_Init(void); //外部中断初始化#endifexti.cvoid EXTIX_Init(void){EXTI_InitTypeDef EXTI_InitStructure; //外部中断结构体初始化NVIC_InitTypeDef NVIC_InitStructure; //中断分组结构体初始化KEY_Init();RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO时钟GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //映射IO⼝与中断线//以下为配置中断线初始化EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能中断线EXTI_InitStructure.EXTI_Line = EXTI_Line0; //中断线标号EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //触发⽅式EXTI_Init(&EXTI_InitStructure);//以下为中断优先级的配置NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //声明使⽤的中断是哪⼀个NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //设置抢占优先级为2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //设置⼦优先级为3NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断NVIC_Init(&NVIC_InitStructure);}void EXTI0_IRQHandler(void) //中断服务函数{delay_ms(10); //软件去抖if(WK_UP==1){LED0 = !LED0;LED1 = !LED1;}EXTI_ClearITPendingBit(EXTI_Line0); //清除中断位}补充中断服务函数中断服务函数的名称是固定的,写错会导致⽆法中断。
STM32单片机实现外部中断的步骤及方法
![STM32单片机实现外部中断的步骤及方法](https://img.taocdn.com/s3/m/2ed5937877232f60ddcca1e0.png)
{
if(EXTI_GetITStatus(EXTI_Line0)==SET)
{
EXTI-》PR=0X01;
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0)==Bit_RESET)
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
{
if(EXTI_GetITStatus(EXTI_Line0)==SET)
{
EXTI_ClearITPendingBit(EXTI_Line0);
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0)==Bit_RESET)
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
}
}
其中最重要的一点:需要注意进入服务程序后清除中断标志位;
说几点容易忽略的地方:
1.中断服务程序一定要清除中断标志位;
2.联结相应端口与中断线;
3.按键端口设置成上拉输入;
4.在配置EXTI时清除中断标志位;
按键部分的短路自己连的:
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
}
}
}
下面是整个用函数代码:
#include“stm32f10x.h”
voidGPIO_Config();
voidNVIC_Configuration();
voidEXTI_Configuration();
stm32外部中断实验原理
![stm32外部中断实验原理](https://img.taocdn.com/s3/m/5ecb916d657d27284b73f242336c1eb91a3733d7.png)
stm32外部中断实验原理STM32是意法半导体公司推出的一款32位单片机系列产品,具有高性能、低功耗和广泛的外设功能。
其中外部中断是其重要的功能之一,可以实现外部事件的异步处理,适用于各种实时应用。
外部中断的原理是通过外部引脚和STM32之间的触发信号来实现中断的触发和处理。
STM32支持多种中断模式,包括上升沿触发、下降沿触发、双边沿触发和低电平触发等。
如何使用外部中断呢?首先,在程序中需要使用到外部中断的引脚上要连接一个外部触发源,比如按键或传感器等。
然后,在程序中对该引脚进行配置,指定外部中断的触发方式。
接下来,在程序中编写中断处理函数,在中断触发时执行相应的处理逻辑。
最后,在启动中断之前,需要使能相应的中断,并配置优先级。
STM32外部中断是基于NVIC(Nested Vectored Interrupt Controller)的,它是ARM Cortex-M处理器的一部分。
它能够支持多重中断,并可配置中断优先级。
当一个外部中断触发时,会产生一个中断请求,然后被NVIC捕获,并根据优先级进行中断处理。
在硬件层面上,外部中断将通过外部中断控制器(EXTI)和GPIO控制器进行连接。
外部中断的引脚通过GPIO控制器配置为中断模式,并通过EXTI控制器与NVIC连接。
当外部触发源产生中断信号时,通过GPIO控制器将该中断信号传递给EXTI控制器,然后触发中断处理。
在软件编程方面,首先需要对GPIO和EXTI进行相应的初始化配置。
对于GPIO,我们需要设置引脚的模式、速度和上下拉等参数。
对于EXTI,我们需要设置中断触发方式(例如上升沿触发)和中断屏蔽(可以选择屏蔽或非屏蔽中断)等。
接着,使用STM32提供的库函数进行中断处理的配置。
首先,我们需要使用NVIC_Init函数来配置NVIC,使能相应的中断和设置中断优先级。
然后,使用EXTI_Init函数设置外部中断的触发方式和屏蔽等。
最后,编写中断处理函数,当外部中断触发时进行相应的处理。
STM32外部中断总结
![STM32外部中断总结](https://img.taocdn.com/s3/m/0a778bd926fff705cc170a58.png)
STM32 外部中断配置总结一:触发方式STM32 的外部中断是通过边沿来触发的,不支持电平触发;二:外部中断分组STM32 的每一个GPIO 都能配置成一个外部中断触发源,STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0为第一组,那么依此类推,我们能得出一共有16 组,STM32 规定,每一组中同时只能有一个中断触发源工作,那么,最多工作的也就是16个外部中断。
STM32 分组和对应中断处理函数分配:三:外部中断的配置过程配置触发源 -GPIO触发源为通过GPIO 端口输入,所以,要配置GPIO 的模式,输入方式,输入方式有以下几种:1.GPIO_Mode_AIN ,模拟输入(ADC 模拟输入,或者低功耗下省电)2.GPIO_Mode_IN_FLOATING ,浮空输入3.GPIO_Mode_IPD = 0x28,带下拉输入4.GPIO_Mode_IPU = 0x48,带上拉输入管脚 中断标志 中断处理函数分配PA0~PG0 EXTI0 EXTI0_IRQHandlerPA1~PG1 EXTI1 EXTI1_IRQHandlerPA2~PG2 EXTI2 EXTI2_IRQHandlerPA3~PG3 EXTI3 EXTI3_IRQHandler PA4~PG4 EXTI4 EXTI4_IRQHandler PA5~PG5 EXTI5 EXTI9_5_IRQHandler PA6~PG6 EXTI6 PA7~PG7 EXTI7 PA8~PG8 EXTI8 PA9~PG9 EXTI9 PA10~PG10 EXTI10 EXTI15_10_IRQHandler PA11~PG11 EXTI11 PA12~PG12 EXTI12 PA13~PG13 EXTI13 PA14~PG14 EXTI14 PA15~PG15 EXTI15●引脚与外部中断关联●外部中断AFIO时钟开启●外部中断配置这个主要是中断线路选择,中断触发方式,中断使能。
STM32GPIO外部中断总结
![STM32GPIO外部中断总结](https://img.taocdn.com/s3/m/deeb5bd451e2524de518964bcf84b9d529ea2c55.png)
GPIO引脚中断标志位中断处理函数PA0~PG0EXTI0EXTI0_IRQHandlerPA1~PG1EXTI1EXTI1_IRQHandlerPA2~PG2EXTI2EXTI2_IRQHandlerPA3~PG3EXTI3EXTI3_IRQHandlerPA4~PG4EXTI4EXTI4_IRQHandlerPA5~PG5EXTI5EXTI9_5_IRQHandler PA6~PG6EXTI6PA7~PG7EXTI7PA8~PG8EXTI8PA9~PG9EXTI9PA10~PG10EXTI10EXTI15_10_IRQHandler PA11~PG11EXTI11PA12~PG12EXTI12PA13~PG13EXTI13PA14~PG14EXTI14PA15~PG15EXTI15STM32GPIO外部中断总结⼀、STM32中断分组: STM32 的每⼀个GPIO都能配置成⼀个外部中断触发源,这点也是 STM32 的强⼤之处。
STM32 通过根据引脚的序号不同将众多中断触发源分成不同的组,⽐如:PA0,PB0,PC0,PD0,PE0,PF0,PG0为第⼀组,那么依此类推,我们能得出⼀共有16 组,STM32 规定,每⼀组中同时只能有⼀个中断触发源⼯作,那么,最多⼯作的也就是16个外部中断。
STM32F103 的中断控制器⽀持 19 个外部中断/事件请求。
每个中断设有状态位,每个中断/事件都有独⽴的触发和屏蔽设置。
STM32F103 的19 个外部中断为:线 0~15:对应外部 IO ⼝的输⼊中断。
线 16:连接到 PVD 输出。
线 17:连接到 RTC 闹钟事件。
线 18:连接到 USB 唤醒事件。
⼆:外部中断的配置过程: 1、配置触发源GPIO⼝: 因为GPIO⼝作为触发源使⽤,所以将GPIO⼝配置成输⼊模式,触发模式有以下⼏种: a.GPIO_Mode_AIN ,模拟输⼊(ADC模拟输⼊,或者低功耗下省电) b.GPIO_Mode_IN_FLOATING ,浮空输⼊ c.GPIO_Mode_IPD ,带下拉输⼊ d.GPIO_Mode_IPU ,带上拉输⼊ GPIO_InitTypeDef GPIO_InitStructure;//定义结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//选择IO⼝ PE2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//设置成上拉输⼊ GPIO_Init(GPIOE, &GPIO_InitStructure);//使⽤结构体信息进⾏初始化IO⼝ 2、使能AFIO复⽤时钟功能: RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); 3、将GPIO⼝与中断线映射起来: GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); 4、中断线上进⾏中断初始化: EXTI_InitTypeDef EXTI_InitStructure;//定义初始化结构体 EXTI_InitStructure.EXTI_Line=EXTI_Line2; //中断线的标号取值范围为EXTI_Line0~EXTI_Line15 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式,可选值为中断 EXTI_Mode_Interrupt 和事件 EXTI_Mode_Event。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4bit的中断优先级可以分成2组,从高位看,前面定义的是抢占式优先级,后面是响应优先级。按照这种分组,4bit一共可以分成5组
}
设置相应的时钟所需要的RCC函数在stm32f10x_rcc.c中,所以要在工程中添加此文件。
2. 设置好相应的中断
设置相应的中断实际上就是设置NVIC,在STM32的固件库中有一个结构体NVIC_InitTypeDef,里面有相应的标志位设置,然后再用NVIC_Init()函数进行初始化。详细代码如下:
第0组:所有4bit用于指定响应优先级;
第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级;
第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级;
第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级;
第4组:所有4位用于指定抢占式优先级。
所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQChannel; //选择中断通道3
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占式中断优先级设置为1
NVIC_Init(&NVIC_InitStructure);
}
由于有3个中断,因此根据前文所述,需要有3个bit来指定抢占优先级,所以选择第2组。又由于EXTI5-9共用一个中断响应函数,所以EXTI5选择的中断通道是EXTI9_5_IRQChannel,详细信息可以在头文件中查询得到。用到的NVIC相关的库函数在stm32f10x_nivc.c中,需要将此文件复制并添加到工程中。具体位置可以查看关于GPIO的笔记。这段代码编译起来没有任何问题,但是在链接的时候就会报错,需要把STM32F10xR.LIB加入工程中,具体位置在…KeilARMRV31LIBSTSTM32F10xR.LIB。
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //选择输入模式为浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉电阻输出
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //响应式中断优先级设置为2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
2 GPIO外部中断
STM32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组位一个单位的,同组间的外部中断同一时间只能使用一个。比如说,PA0,PB0,PC0,PD0,PE0,PF0,PG0这些为1组,如果我们使用PA0作为外部中断源,那么别的就不能够再使用了,在此情况下,我们智能使用类似于PB1,PC2这种末端序号不同的外部中断源。每一组使用一个中断标志EXTIx。EXTI0 – EXTI4这5个外部中断有着自己的单独的中断响应函数,EXTI5-9共用一个中断响应函数,EXTI10-15共用一个中断响应函数。
NVIC_Init(&NVIC_InitStructuure.NVIC_IRQChannel = EXTI9_5_IRQChannel; //选择中断通道5
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占式中断优先级设置为2
1. 设置相应的时钟
首先需要打开GPIOB、GPIOC和GPIOE(因为按键另外一端连接的是PE口)。然后由于是要用于触发中断,所以还需要打开GPIO复用的时钟。相应的函数在GPIO的学习笔记中有了详细了解释。详细代码如下:
void RCC_cfg()
{
//打开PE PD PC PB端口时钟,并且打开复用时钟
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQChannel; //选择中断通道2
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占式中断优先级设置为0
当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义2个优先级。
中断对于开发嵌入式系统来讲的地位绝对是毋庸置疑的,在C51单片机时代,一共只有5个中断,其中2个外部中断,2个定时/计数器中断和一个串口中断,但是在STM32中,中断数量大大增加,而且中断的设置也更加复杂。今天就将来探讨一下关于STM32中的中断系统。
1 基本概念
ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。
5. 在选择的中断通道的响应函数中中断函数。
由于我用的奋斗开发板没有引出相应的芯片引脚,所以只能用按键来触发相应的中断。根据原理图,K1/K2/K3连接的是PC5/PC2/PC3,因此我将用EXTI5/EXTI2/EXTI3三个外部中断。PB5/PD6/PD3分别连接了三个LED灯。中断的效果是按下按键,相应的LED灯将会被点亮。
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉电阻输出
有几点需要注意的是:
1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;
2)抢占式优先级别相同的中断源之间没有嵌套关系;
3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //响应式中断优先级设置为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中断
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_ResetBits(GPIOE,GPIO_Pin_2); //将PE.2引脚设置为低电平输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5; //选择引脚2 3 5
3 程序开发
其实上面那些基本概念和知识只是对STM32的中断系统有一个大概的认识,用程序说话将会更能够加深如何使用中断。使用外部中断的基本步骤如下:
1. 设置好相应的时钟;
2. 设置相应的中断;
3. IO口初始化;
4. 把相应的IO口设置为中断线路(要在设置外部中断之前)并初始化;
对于中断的控制,STM32有一个专用的管理机构:NVIC。对于NVIC的详细解释,可以参考《ARM Cortex-M3权威指南》,Joseph Yiu著,宋岩译,北京航空航天大学出版社出版,第8章NVIC与中断控制。中断的使能,挂起,优先级,活动等等部都是NVIC在管理的。因为我学习STM32重点在于如何开发程序,所以内部的一些东西,在此我就不详细说明了,有感兴趣的可以参看上面提到的那本数。
3. IO口初始化
void IO_cfg()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //选择引脚2
GPIO_Init(GPIOC,&GPIO_InitStructure); //设置PC.2/PC.3/PC.5