tag 标签: 外部中断

相关博文
  • 热度 3
    2021-5-9 23:50
    2145 次阅读|
    1 个评论
    凡是只需要设置一次的,都可以放在初始化函数中 1.选择触发边沿 2.关闭软件中断、事件功能 3.开启模块级中断使能 4.开启核心级中断使能 中断服务函数 1.标志位:挂起请求寄存器 20210522对上述内容更新 配置外部中断的步骤: 1.GPIO相关的库函数 2.EXTI相关的函数 3.NVIC相关的函数 4.中断服务函数
  • 热度 18
    2013-6-26 20:23
    943 次阅读|
    0 个评论
    STM32F103有76个中断,包括16个内核中断和60个可屏蔽中断,具有16级16级可编程的中断优先级。 理解STM32的中断,要从中断优先级哦分组开始。而理解中断优先级分组,就要理解什么是抢占优先级,什么是响应优先级。 所谓: 抢占优先级:如果有两中断先后出发,已经在执行的中断优先级如果没有后出发的中断优先级高,就会先处理抢占优先级高的中断,也就是说有较高的抢占优先级的中断可以打断抢占优先级较低的中断,这是实现中断嵌套的基础。 响应优先级:只在同一抢占优先级的中断同时触发时起作用。抢占优先级相同,则优先执行响应优先级较高的中断。响应优先级不会造成中断的嵌套,如果中断的两个优先级都一致,那么优先执行位于中断向量表中位置较高的中断。 STM32通过中断向量控制器(NVIC)来分配抢占优先级和响应优先级的数量。 ARM cortex-m3内核中有一个3位宽度的PRIGROUP数据区,用来指示一个8位数据序列中的小数点的位置从而表示中断优先级的分组。 如果PRIGROUP数据位为000,即为0,说明8位数据序列中小数位置在第1位的左边,为xxxxxxx.y 。用于表示中断优先级的分组的含义就是:用7位的数据宽度来表示抢占优先级的数量,即为128,用1位的数据宽度来表示响应优先级的数量即为2。 STM32中只有5个优先级分组,表示方法略有不同: MDK中定义的中断相关的寄存器结构体为: typedef struct {   vu32 ISER ;   u32  RESERVED0 ;   vu32 ICER ;   u32  RSERVED1 ;   vu32 ISPR ;   u32  RESERVED2 ;   vu32 ICPR ;   u32  RESERVED3 ;   vu32 IABR ;   u32  RESERVED4 ;   vu32 IPR ; } NVIC_TypeDef; 其中: ISER 全称是interupt set-Enable Registers,这是以讹中断使能寄存器组。ISER 的bit0~bit31分别对应中断0~31.ISER 的bit0~bit27对应中断32~59,要是能某个中断,必须设置相应的ISER位为1,使该中断被使能。 ICER全称是Interrupt clear-Enable Registers中断清除寄存器组。该寄存器组的功能与ISER的作用恰好相反,是用来清除某个走红段的使能的。 ISPR全称是Interrupt set-Enable Registers,中断挂起控制寄存器。通过置1,可以将正在进行的中断挂起,而执行同级或更高级别的中断,写0无效。 ICPR全称是Interrupt clear-Enable Registers,中断解挂控制寄存器,通过设置1,可以将挂起的中断解挂,置0无效。 IABR全称是Active Bit Registers,是中断激活标志位寄存器组。对应位所代表的中断和ISER一样,如果为1,则表示该位所对应的中断正在被执行。 IPR 全称是Interrupt Priority Registers,是中断优先级控制的寄存器。IPR寄存器由15个32bit的寄存器组成,每个可屏蔽中断用8bit,IPR 的 , , , 分别对应中断3~0。 每个可屏蔽中断占用的8bit并没有全部使用,只用了高4位,这4位又分为抢占优先级和响应优先级。 一般把IO口作为外部中断输入的步骤: 1.初始化IO口为输入 2.开启IO口服用时钟,设置IO口与中断线的映射关系 3.开启与该IO口相对应的线上中断/事件,设置触发条件 4.配置中断分组(NVIC),并使能中断 5.编写中断服务函数  
  • 热度 19
    2013-6-26 20:23
    988 次阅读|
    0 个评论
    分享一下中断程序: void EXTIX_Init(void) { GPIO_InitTypeDef   GPIO_InitStructure;   //定义端口结构初始化 EXTI_InitTypeDef   EXTI_InitStructure;   //定义中断结构初始化 NVIC_InitTypeDef   NVIC_InitStructure; //定义中断优先级结构初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO,ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);     //改变指定管脚的映射 GPIO_Remap_SWJ_Disable SWJ PIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);     //改变指定管脚的映射GPIO_Remap_SWJ_JTAGDisable //初始化KEY01- PB5,  KEY00-PB4  设置为输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, GPIO_InitStructure); KEY01 = 1; KEY00 = 0; //初始化KEY13-PB3 设置为输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, GPIO_InitStructure); //初始化KEY12-PC12, KEY11-PC11, KEY10-PC10,设置为输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_11|GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource3);          EXTI_InitStructure.EXTI_Line = EXTI_Line3; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(EXTI_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource12); GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource11); GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource10); EXTI_InitStructure.EXTI_Line = EXTI_Line12; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(EXTI_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_Line11; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(EXTI_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_Line10; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(NVIC_InitStructure);  } void EXTI3_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line3) !=RESET) { LED4 =!LED4; } EXTI_ClearITPendingBit(EXTI_Line3); } void EXTI15_10_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line12) !=RESET) { LED3 =!LED3; } else if (EXTI_GetITStatus(EXTI_Line11) !=RESET) { LED2 =!LED2;  } else if (EXTI_GetITStatus(EXTI_Line10) !=RESET) { LED1 =!LED1; } EXTI_ClearITPendingBit(EXTI_Line12);      //清除EXTI线路挂起位 EXTI_ClearITPendingBit(EXTI_Line11);      //清除EXTI线路挂起位 EXTI_ClearITPendingBit(EXTI_Line10);      //清除EXTI线路挂起位 }
  • 热度 19
    2013-1-13 14:52
    1568 次阅读|
    0 个评论
    第十章 外部中断实验       这一章,我们将向大家介绍如何使用STM32的外部输入中断。在前面几章的学习中,我们掌握了STM32的IO口最基本的操作。本章我们将介绍如何将STM32的IO口作为外部中断输入,在本章中,我们将以中断的方式,实现我们在第八章所实现的功能。本章分为如下几个部分: 10.1 STM32外部中断简介 10.2 硬件设计 10.3 软件设计 10.4 下载验证 详细内容和源码,见附件!
  • 热度 17
    2012-12-24 14:23
    7968 次阅读|
    2 个评论
    实现功能:外部中断线0(PA0)与线15(PA15)分别连接到两个按钮,一个按钮用于产生上升沿,另一个用于产生下降沿,两个中断函数里均对PA8口连接的led灯取反,同时PD2连接的led灯随意延时取反指示程序运行。 这次我用了官方提供的例程来构建自己的工程,这样可以省下不少时间,而且减少了出错率,调试起来容易多了。   首先是stm32中断与外部中断的概念。 ARM Coetex-M3内核共支持256个中断,其中16个内部中断,240个外部中断和可编程的256级中断优先级的设置。STM32目前支持的中断共84个(16个内部+68个外部),还有16级可编程的中断优先级的设置,仅使用中断优先级设置8bit中的高4位。 STM32可支持68个中断通道,已经固定分配给相应的外部设备,每个中断通道都具备自己的中断优先级控制字节PRI_n(8位,但是STM32中只使用4位,高4位有效),每4个通道的8位中断优先级控制字构成一个32位的优先级寄存器。68个通道的优先级控制字至少构成17个32位的优先级寄存器。 4bit的中断优先级可以分成2部分,从高位看,前面定义的是抢占式优先级,后面是响应优先级。4bit一共可以分成5组。 第0组:所有4bit用于指定响应优先级; 第1组:最高1位用于指定抢占式优先级,后面3位用于指定响应优先级; 第2组:最高2位用于指定抢占式优先级,后面2位用于指定响应优先级; 第3组:最高3位用于指定抢占式优先级,后面1位用于指定响应优先级; 第4组:所有4位用于指定抢占式优先级。 所谓抢占式优先级和响应优先级,他们之间的关系是:具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套。 1、  当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后 才能被处理。 2、  如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个; 3、  3如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。每一个中断源都必须定义2个优先级。 有几点需要注意的是: 1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果; 2)抢占式优先级别相同的中断源之间没有嵌套关系; 3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。   STM32有20个外部中断线,其中EXTI0-EXTI15给I/O端口使用,对应如下图: EXTI线16连接到PVD输出  EXTI线17连接到RTC闹钟事件  EXTI线18连接到USB唤醒事件 EXTI线19连接到以太网唤醒事件(只适用于互联型产品)。   其中,每个外部中断都具有对应的硬件机制,如下图:   STM32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组位一个单位的,同组间的外部中断同一时间只能使用一个。比如说,PA0,PB0,PC0,PD0,PE0,PF0,PG0这些为1组,如果我们使用PA0作为外部中断源,那么别的就不能够再使用了,在此情况下,我们只能使用类似于PB1,PC2这种末端序号不同的外部中断源。每一组使用一个中断标志EXTIx。EXTI0 – EXTI4这5个外部中断有着自己的单独的中断响应函数,EXTI5-9共用一个中断响应函数,EXTI10-15共用一个中断响应函数。但是在中断函数里面可以查询中断标志,从而判断是哪个外部中断,虽然共用同一个中断号,但是具有独立的中断标志位EXTI_LineX,X为0~15。   使用外部中断需要准备的工作如下: 1、初始化IO口为输入。 这一步设置你要作为外部中断输入的IO口的状态,可以设置为上拉/下拉输入,也可以设置为浮空输入,但浮空的时候外部一定要带上拉,或者下拉电阻。否则可能导致中断不停的触发。在干扰较大的地方,就算使用了上拉/下拉,也建议使用外部上拉/下拉电阻,这样可以一定程度防止外部干扰带来的影响。 2、开启IO口的复用时钟。 3、开启与该IO口相对应的线上中断/事件,设置触发条件。 4、配置NVIC,并使能中断。 5、编写相应中断函数。     下面是main.c文件源码   //main.c #include "stm32f10x.h" EXTI_InitTypeDef   EXTI_InitStructure; GPIO_InitTypeDef   GPIO_InitStructure; NVIC_InitTypeDef   NVIC_InitStructure;   void GPIO_Config(void); void EXTI0_Config(void); void EXTI15_10_Config(void); void delay(void);   int main(void) {   GPIO_Config();   /* Configure PA.00 in interrupt mode */   EXTI0_Config();   /* Configure PA.15 in interrupt mode */   EXTI15_10_Config();           while (1)   {   GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_RESET);   delay();   GPIO_WriteBit(GPIOD, GPIO_Pin_2, Bit_SET);   delay();   } }   void delay(void) { u16 i,j; for(i=0;i1000;i++) for(j=0;j1000;j++) ; } void GPIO_Config(void) {   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);   /* Configure PA.08 pin as output */   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   GPIO_Init(GPIOA, GPIO_InitStructure);     /* Configure PD.02 pin as output */   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   GPIO_Init(GPIOD, GPIO_InitStructure); }     /**   * @brief  Configure PA.00 in interrupt mode   * @param  None   * @retval None   */ void EXTI0_Config(void) {   /* Enable GPIOA clock */   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   /* Configure PA.00 pin as input*/   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;   GPIO_Init(GPIOA, GPIO_InitStructure);     /* Enable AFIO clock */   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);     /* Connect EXTI0 Line to PA.00 pin */   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);     /* Configure EXTI0 line */   EXTI_InitStructure.EXTI_Line = EXTI_Line0;   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;    EXTI_InitStructure.EXTI_LineCmd = ENABLE;   EXTI_Init(EXTI_InitStructure);     /* Enable and set EXTI0 Interrupt to the lowest priority */   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   NVIC_Init(NVIC_InitStructure); }   /**   * @brief  Configure PA.15 in interrupt mode   * @param  None   * @retval None   */ void EXTI15_10_Config(void) {     /* Enable GPIOA clock */   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     /* Configure PA.15 pin as input*/   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   GPIO_Init(GPIOA, GPIO_InitStructure);     /* Enable AFIO clock */   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);   /* Connect EXTI15 Line to PA.15 pin */   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource15);     /* Configure EXTI15 line */   EXTI_InitStructure.EXTI_Line = EXTI_Line15;   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   EXTI_InitStructure.EXTI_LineCmd = ENABLE;   EXTI_Init(EXTI_InitStructure);     /* Enable and set EXTI15_10 Interrupt to the lowest priority */   NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0E;   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;     NVIC_Init(NVIC_InitStructure);   }         下面是中断函数的源码。   //stm32f10x_it.c #include "stm32f10x_it.h"   u8 flag=0;   /**   * @brief  This function handle External line 0 interrupt request.   * @param  None   * @retval None   */ void EXTI0_IRQHandler(void) {   if(EXTI_GetITStatu(EXTI_Line0) != RESET)   {          if(flag)              {               GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);               flag=0;               }         else              {               GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);               flag=1;               }     /* Clear the  EXTI line 0 pending bit */     EXTI_ClearITPendingBit(EXTI_Line0);   } }   /**   * @brief  This function handle External lines 15 to 10 interrupt request.   * @param  None   * @retval None   */ void EXTI15_10_IRQHandler(void) {   if(EXTI_GetITStatu(EXTI_Line15) != RESET)   {         if(flag)              {               GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);               flag=0;               }         else              {               GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);               flag=1;               }       /* Clear the  EXTI line 15 pending bit */     EXTI_ClearITPendingBit(EXTI_Line15);   } }   编程配置后,可以看到连接到PD2上的led不断闪烁,按下PA0和PA15上任意一个按钮均可取反连接到PA8上的led灯。
相关资源