精华内容
下载资源
问答
  • 中断

    2020-12-04 20:39:16
    3. 中断有一个中断向量表,里面存放着发生中断后需要做出处理的中断函数的指针,然后通过这个指针去寻找这个函数的实现。 4. 使用的ST32F429的芯片的中断向量表是放在flash里面的,这些存放中断函数指针的中断向量表...
    一般情况下将异常也看成中断:
    
    1. 中断分为 系统异常 和 外设中断
    2. 这些都可以从数据手册可查
    3. 中断有一个中断向量表,里面存放着发生中断后需要做出处理的中断函数的指针,然后通过这个指针去寻找这个函数的实现。
    4. 使用的ST32F429的芯片的中断向量表是放在flash里面的,这些存放中断函数指针的中断向量表的地址是从0x0000000开始的,其实flash映
    5. 射的地址是有其他地址的,但是这里有重新映射了,就好比是地址偏移。
    6. NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。
    7. 两个重要的库文件:core_cm4.h 和 misc.h
    8. NVIC是一个外设,它有很多寄存器,就和GPIO一样,寄存器写成结构体如下:
    9. typedef struct
    {
      __IO uint32_t ISER[8];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */
           uint32_t RESERVED0[24];
      __IO uint32_t ICER[8];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register         */
           uint32_t RSERVED1[24];
      __IO uint32_t ISPR[8];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register          */
           uint32_t RESERVED2[24];
      __IO uint32_t ICPR[8];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register        */
           uint32_t RESERVED3[24];
      __IO uint32_t IABR[8];                 /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register           */
           uint32_t RESERVED4[56];
      __IO uint8_t  IP[240];                 /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */
           uint32_t RESERVED5[644];
      __O  uint32_t STIR;                    /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register     */
    }  NVIC_Type;
    
    10.中断的话有中断优先级,一般的中断都可以设置优先级的(NVIC下的IP寄存器设置),所以相同的优先级就需要进行仲裁判断,这时候就
    11.出现了优先级分组,优先级的分组由内核外设 SCB 的应用程序中断及复位控制寄存器 AIRCR 的PRIGROUP[10:8]位决定, F429 分为
    12.5 组。
    

    在这里插入图片描述
    在这里插入图片描述

    typedef struct
    {
      uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
                                                       This parameter can be an enumerator of @ref IRQn_Type 
                                                       enumeration (For the complete STM32 Devices IRQ Channels
                                                       list, please refer to stm32f4xx.h file) */
    
      uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                       specified in NVIC_IRQChannel. This parameter can be a value
                                                       between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
                                                       A lower priority value indicates a higher priority */
    
      uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                       in NVIC_IRQChannel. This parameter can be a value
                                                       between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
                                                       A lower priority value indicates a higher priority */
    
      FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
                                                       will be enabled or disabled. 
                                                       This parameter can be set either to ENABLE or DISABLE */   
    } NVIC_InitTypeDef;
    
    初始化之后调用:void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)函数写进去。
    
    展开全文
  • STM32—中断详解(配合按键中断代码,代码亲测)

    万次阅读 多人点赞 2019-07-25 17:35:23
    在STM32中执行中断主要分三部分: 1.配置NVIC_Config()函数 ...NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。 NVIC_Config()函数代码如下: s...

    在STM32中执行中断主要分三部分:
    1.配置NVIC_Config()函数
    2.配置EXTI_Config()函数
    3.编写中断服务函数

    (注:本文章所用代码为中断按键代码,实现了按键进入中断从而控制LED亮灭)

    配置NVIC_Config()函数

    NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。
    NVIC_Config()函数代码如下

    static void NVIC_Config(void) /* 主要是配置中断源的优先级与打开使能中断通道 */
    {
    	NVIC_InitTypeDef NVIC_InitStruct ;
    	
    	/* 配置中断优先级分组(设置抢占优先级和子优先级的分配),在函数在misc.c */
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1) ;
    	
    	/* 配置初始化结构体 在misc.h中 */
    	/* 配置中断源 在stm32f10x.h中 */
    	NVIC_InitStruct.NVIC_IRQChannel = KEY1_EXTI_IRQN ;
    	/* 配置抢占优先级 */
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1 ;
    	/* 配置子优先级 */
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0 ;
    	/* 使能中断通道 */
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE ;
    	/* 调用初始化函数 */
    	NVIC_Init(&NVIC_InitStruct) ;
    	
    	/* 对key2执行相同操作 */
    	NVIC_InitStruct.NVIC_IRQChannel = KEY2_EXTI_IRQN ;
    	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1 ;
    	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1 ;
    	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE ;
    	NVIC_Init(&NVIC_InitStruct) ;
    	
    }
    

    配置NVIC_Config()的目的是选择中断源的优先级以及打开中断通道,主要功能通过配置NVIC初始化结构体NVIC_InitStruct来完成。通俗的讲,STM32中有很多中断,而当有多个中断同时发生时就涉及到中断执行的先后问题了,所以引入了中断优先级的概念,中断优先级越高中断就越先执行。在这里我们只讨论外部中断的优先级,在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级。优先级高低的比较包括抢占优先级和子优先级,先比较抢占优先级,如果抢占优先级相同就比较子优先级,从而得出中断之间的优先级高低。NVIC的主要任务就是给对应的中断源分配中断优先级。 中断优先级分配的原理繁杂,但固件库编程的好处就是化繁为简,我们只需要按照NVIC_InitStruct()中的内容进行配置就行。

    接下来简单讲解一下NVIC_Config()函数的内容:
    1.首先设置中断优先级分组
    中断优先级分组其实是确立一个大纲,中断优先级寄存器 NVIC_IPRx中有4个位用来确定优先级,中断优先级的分组就是把这4个位分配在抢占优先级和子优先级中。比如设定一个位配置抢占优先级,其余三个位配置子优先级。通过函数NVIC_PriorityGroupConfig() ; 实现分组,详细代码如下:

    1 /**
    2 * 配置中断优先级分组:抢占优先级和子优先级
    3 * 形参如下:
    4 * @arg NVIC_PriorityGroup_0: 0bit for 抢占优先级
    5 *                   		   4 bits for 子优先级
    6 * @arg NVIC_PriorityGroup_1: 1 bit for 抢占优先级
    7 *                            3 bits for 子优先级
    8 * @arg NVIC_PriorityGroup_2: 2 bit for 
    9 *                            2 bits for 子优先级
    10 * @arg NVIC_PriorityGroup_3: 3 bit for 抢占优先级
    11 *                           1 bits for 子优先级
    12 * @arg NVIC_PriorityGroup_4: 4 bit for 抢占优先级
    13 *                           0 bits for 子优先级
    14 * @注意 如果优先级分组为 0,则抢占优先级就不存在,优先级就全部由子优先级控制
    15 */
    16 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
    17 {
    18 // 设置优先级分组
    19 SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
    20 }
    

    2.优先级分组完毕后,是配置NVIC初始化结构体

    typedef struct {
    2 uint8_t NVIC_IRQChannel; // 中断源
    3 uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
    4 uint8_t NVIC_IRQChannelSubPriority; // 子优先级
    5 FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
    6 } NVIC_InitTypeDef;
    

    初始化结构体的作用是,收集中断源的信息(包括配置的是哪一个中断源、中断源的抢占优先级是多少、中断源的子优先级是多少、中断源的使能是否开启)。
    NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序也不会报错,只会导致不响应中断。 stm32f10x.h 头文件里面的 IRQn_Type 结构体定义,这个结构体包含了所有的中断源。
    NVIC_IRQChannelPreemptionPriority和NVIC_IRQChannelSubPriority 分别设置抢占优先级和子优先级,具体的值要根据中断优先级分组来确定。
    NVIC_IRQChannelCmd:设置中断使能(ENABLE)或者失能(DISABLE),相当于一个电源总开关。
    3.最后借助NVIC初始化函数将NVIC初始化结构体中的信息写入相应的寄存器中 (体现了固件库编程的优点,不需要我们深入到寄存器层次去,只需要掌握相应函数的配置即可)

    配置EXTI_Config()函数

    EXTI(External interrupt/event controller):外部中断/事件控制器,管理了控制器的 20个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。 EXTI 可以实现对每个中断/事件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
    按我的理解,EXTI是一个有着多达20个接口的控制器,它可以为每一个接入接口的信号源配置中断(或事件)线、设置信号的检测方式、设置触发事件的性质,也就是说,传入EXTI的仅仅是一个信号,EXTI的功能就是根据信号传入的“线”对信号做出相应的处理,然后将处理后的信号转向NVIC。 就像一个分拣机器,传入的东西经过筛选处理被送往不同的地方,只是EXTI分拣的是信号罢了。 如果说NVIC是配置中断源,那么EXTI就是向NVIC传送中断信号。

    EXTI功能框图:
    在这里插入图片描述EXTI 可分为两大部分功能,一个是产生中断,另一个是产生事件,线路1-2-4-5是产生中断的流程,20/代表着有20条相同的线路。

    接下来讲解一下EXTI_Config()函数代码:

    void EXTI_Config() /* 主要是连接EXTI与GPIO */
    {
    	GPIO_InitTypeDef GPIO_InitStruct ;
    	EXTI_InitTypeDef EXTI_InitStruct ;
    	
    	NVIC_Config();
    
    	/* 初始化要与EXTI连接的GPIO */
    	/* 开启GPIOA与GPIOC的时钟 */
    	RCC_APB2PeriphClockCmd(KEY1_EXTI_GPIO_CLK | KEY2_EXTI_GPIO_CLK, ENABLE) ;
    	
    	GPIO_InitStruct.GPIO_Pin = KEY1_EXTI_GPIO_PIN ;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
    	GPIO_Init(KEY1_EXTI_GPIO_PORT , &GPIO_InitStruct) ;
    	
    	GPIO_InitStruct.GPIO_Pin = KEY2_EXTI_GPIO_PIN ;
    	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
    	GPIO_Init(KEY2_EXTI_GPIO_PORT , &GPIO_InitStruct) ;
    	
    	/* 初始化EXTI外设 */
    	/* EXTI的时钟要设置AFIO寄存器 */
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE) ;
    	/* 选择作为EXTI线的GPIO引脚 */
    	GPIO_EXTILineConfig( KEY1_GPIO_PORTSOURCE , KEY1_GPIO_PINSOURCE) ;
    	/* 配置中断or事件线 */
    	EXTI_InitStruct.EXTI_Line = KEY1_EXTI_LINE ;
    	/* 使能EXTI线 */
    	EXTI_InitStruct.EXTI_LineCmd = ENABLE ;
    	/* 配置模式:中断or事件 */
    	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt ;
    	/* 配置边沿触发 上升or下降 */
    	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising ;
    	EXTI_Init(&EXTI_InitStruct) ;
    	
    	GPIO_EXTILineConfig( KEY2_GPIO_PORTSOURCE , KEY2_GPIO_PINSOURCE) ;
    	EXTI_InitStruct.EXTI_Line = KEY2_EXTI_LINE ;
    	EXTI_InitStruct.EXTI_LineCmd = ENABLE ;
    	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt ;
    	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling ;
    	EXTI_Init(&EXTI_InitStruct);
    }
    
    

    代码可大体分为三部分:
    配置GPIO相应引脚、配置EXTI并连接GPIO引脚、传入NVIC_Config()
    1.配置GPIO相应引脚
    该代码是通过按键产生一个电平信号,然后经EXTI处理传入NVIC产生中断的,所以要配置连接按键的GPIO引脚,主要是设置相应的引脚模式为浮空输入 。老规矩,先开启相应GPIO的时钟,然后配置引脚初始化结构体,再利用初始化函数将初始化结构体写入寄存器中。
    2.配置EXTI并连接GPIO引脚
    要操作外设,首先要打开相关的时钟,EXTI挂载在APB2总线上,并且开启时钟时要操作AFIO寄存器 ,准备工作就绪后连接GPIO相应的引脚到EXTI中,前面说了EXTI有20个接口,所以特定的引脚有特定的接口,所以要根据GPIO_EXTILineConfig();函数选择用作EXTI线的GPIO引脚,函数说明如下

    /**
      * @brief  Selects the GPIO pin used as EXTI Line.
      * @param  GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.
      *   This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).
      * @param  GPIO_PinSource: specifies the EXTI line to be configured.
      *   This parameter can be GPIO_PinSourcex where x can be (0..15).
      * @retval None
      */
    void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
    {
      uint32_t tmp = 0x00;
      /* Check the parameters */
      assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
      assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
      
      tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
      AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
      AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
    }
    

    其实对应的EXTI线就对应GPIO引脚号,这样看起来还比较直观。
    连接好GPIO引脚与EXTI后就该配置EXTI的初始化结构体了,结构体如下:

    typedef struct 
    {
    	 uint32_t EXTI_Line; // 中断/事件线
    	 EXTIMode_TypeDef EXTI_Mode; // EXTI 模式
    	 EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
    	 FunctionalState EXTI_LineCmd; // EXTI 使能
     } EXTI_InitTypeDef;
    

    配置此结构体主要是:选择相应的EXTI线 、选择触发模式、选择产生的结果(中断还是事件)、是否使能EXTI线。
    EXTI_Line:中断线选择,可选 EXTI_0 至 EXTI_19(一共20个)。既然刚才配置好了与GPIO引脚对应的EXTI线,所以初始化结构体中的EXTI线就是与GPIO连接的那个线。
    EXTI_Mode: EXTI 模式选择,可选为产生中断或者产生事件。就是决定信号的发展方向,是产生中断呢?还是产生事件呢?此处是中断。
    EXTI_Trigger: EXTI 边沿触发模式,可选上升沿触发、下降 沿 触 发 或 者 上 升 沿 和 下 降 沿 都 触 发。触发信号。
    EXTI_LineCmd:控制是否使能 EXTI 线,可选使能 EXTI 线或禁用。
    初始化结构体配置完毕后交由初始化函数写入相应的寄存器中。
    3.传入NVIC_Config()
    之后就自动传入NVIC中了。。。

    编写中断服务函数

    到这里就万事俱备只欠东风了,中断的触发与处理及优先级定义都已经安排上了,最后一步就是编写中断函数的内容了,只要进入中断就会执行中断函数中的代码,所以这是收尾工作。STM32的中断服务函数不同于51单片机中的中断服务函数,STM32的所有中断函数都被偷偷安排了,每个中断都有其固定的名字,只有找到这个名字,在这个固定的函数名下编写中断服务函数才是有效的,所有中断函数的编写都要在stm32f10x_it.c 中,如示:
    在这里插入图片描述
    从所给的信息可得知外设的中断服务函数的名字都存放在startup_stm32f10x_xx.s 中,而且是由汇编语言编写,如示:在这里插入图片描述
    可知EXTI线0到EXTI线4线都是单独的中断函数名、EXTI线5到EXTI线9共用一个中断函数名、EXTI线10线到EXTI线15线共用一个中断函数名。
    我们要做的就是以相应的EXTI线的中断函数名字在stm32f10x_it.c中编写中断函数 如下:

    void EXTI0_IRQHandler(void)
    {
    	if(  EXTI_GetITStatus(KEY1_EXTI_LINE)!=RESET)
    	{
    		LED1_TOGGLE;   //LED1的亮灭状态反转
    	}
    		
    	EXTI_ClearITPendingBit(KEY1_EXTI_LINE);
    		
    }
    
    
    void EXTI15_10_IRQHandler(void)
    {
    	if(  EXTI_GetITStatus(KEY2_EXTI_LINE)!=RESET)
    	{
    		LED2_TOGGLE;   //LED2的亮灭状态反转
    	}
    		
    	EXTI_ClearITPendingBit(KEY2_EXTI_LINE);
    		
    }
    
    

    每次进入中断函数后,靠ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)读取中断是否执行 ,执行完之后要利用void EXTI_ClearITPendingBit(uint32_t EXTI_Line)清除清除中断标志位,以免不断进入中断

    大功告成

    到此完整的中断系统就已经完成,主函数只需调用即可!!!
    (附上主函数及俩个头文件)
    希望可以一起交流学习
    qq:2723808286

    #include "stm32f10x.h"
    #include "bsp_led.h"
    #include "bsp_key.h"
    
    int main(void)
    { 
    	LED_GPIO_Config();
    	EXTI_Config();
    	
    	while(1) 
    	{
    	}
    }
    
    
    
    #ifndef __BSP_KEY_H
    #define __BSP_KEY_H
    
    #include "stm32f10x.h"
    
    #define KEY1_EXTI_GPIO_CLK      RCC_APB2Periph_GPIOA
    #define KEY1_EXTI_GPIO_PORT     GPIOA
    #define KEY1_EXTI_GPIO_PIN      GPIO_Pin_0
    #define KEY1_EXTI_IRQN          EXTI0_IRQn      /* 对应着引脚号 */
    #define KEY1_EXTI_LINE          EXTI_Line0      /* 中断、事件线对应引脚号 */
    #define KEY1_GPIO_PORTSOURCE    GPIO_PortSourceGPIOA
    #define KEY1_GPIO_PINSOURCE     GPIO_PinSource0
    #define  KEY1_EXTI_IRQHANDLER       EXTI0_IRQHandler
    
    #define KEY2_EXTI_GPIO_CLK      RCC_APB2Periph_GPIOC
    #define KEY2_EXTI_GPIO_PORT     GPIOC
    #define KEY2_EXTI_GPIO_PIN      GPIO_Pin_13
    #define KEY2_EXTI_IRQN          EXTI15_10_IRQn
    #define KEY2_EXTI_LINE          EXTI_Line13
    #define KEY2_GPIO_PORTSOURCE    GPIO_PortSourceGPIOC
    #define KEY2_GPIO_PINSOURCE     GPIO_PinSource13
    #define  KEY2_EXTI_IRQHANDLER       EXTI15_10_IRQHandler
    
    
    void EXTI_Config(void);
    	
    #endif
    
    
    #ifndef __BSP_LED_H
    #define __BSP_LED_H
    
    #include "stm32f10x.h"
    
    
    
    #define LED1_GPIO_CLK   RCC_APB2Periph_GPIOC   /*时钟*/
    #define LED1_GPIO_PORT  GPIOC                  /*端口*/
    #define LED1_GPIO_PIN   GPIO_Pin_2             /*引脚*/
    
    
    #define LED2_GPIO_PIN   GPIO_Pin_3
    #define LED2_GPIO_CLK   RCC_APB2Periph_GPIOC
    #define LED2_GPIO_PORT  GPIOC
    
    #define digitalTOGGLE(p,i)     {p->ODR ^=i;}
    #define LED1_TOGGLE            digitalTOGGLE(LED1_GPIO_PORT,LED1_GPIO_PIN)
    #define LED2_TOGGLE            digitalTOGGLE(LED2_GPIO_PORT,LED2_GPIO_PIN)  /* LED状态反转 */
     void LED_GPIO_Config(void);                   
    
    #endif
    
    
    
    展开全文
  • 文章目录前言一、NVIC 简介1.NVIC 寄存器简介2.NVIC 中断配置...NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。 1.NVIC 寄存器简介 NVIC 结构体定义,来自固件.


    前言

    STM32中断非常强大,每个外设都可以产生中断


    提示:以下是本篇文章正文内容

    一、NVIC 简介

    NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。

    1.NVIC 寄存器简介

    NVIC 结构体定义,来自固件库头文件:core_cm3.h
    在配置中断的时候我们一般只用 ISER、ICER 和 IP 这三个寄存器,ISER 用来使能中断,ICER 用来失能中断,IP 用来设置中断优先级。
    在这里插入图片描述

    2.NVIC 中断配置固件库

    固件库文件 core_cm3.h 的最后,还提供了 NVIC 的一些函数,这些函数遵循 CMSIS 规则
    在这里插入图片描述

    二、 优先级的定义

    1.优先级定义

    在 NVIC 有一个专门的寄存器:中断优先级寄存器 NVIC_IPRx,用来配置外部中断的优先级,IPR 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255,数值越小,优先级越高。

    2. 优先级分组

    优先级的分组由内核外设 SCB 的应用程序中断及复位控制寄存器 AIRCR 的PRIGROUP[10:8]位决定,F103 分为了 5 组,具体如下:主优先级=抢占优先级
    在这里插入图片描述
    在这里插入图片描述

    三、中断编程步骤

    1.使能外设某个中断

    具体由每个外设的相关中断使能位控制。

    2.初始化 NVIC_InitTypeDef 结构体

    1 typedef struct {
    2 uint8_t NVIC_IRQChannel; // 中断源
    3 uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级
    4 uint8_t NVIC_IRQChannelSubPriority; // 子优先级
    5 FunctionalState NVIC_IRQChannelCmd; // 中断使能或者失能
    6 } NVIC_InitTypeDef;
    

    1)NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序也不会报错,只会导致不响应中断。具体的成员配置可参考 stm32f10x.h 头文件里面的 IRQn_Type 结构体定义,这个结构体包含了所有的中断源。
    2)NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定,具体参考表格 17-5 优先级分组真值表 。
    3)NVIC_IRQChannelSubPriority:子优先级,具体的值要根据优先级分组来确定,具体参考表格 17-5 优先级分组真值表 。
    4)NVIC_IRQChannelCmd:中断使能(ENABLE)或者失能(DISABLE)。操作的是 NVIC_ISER 和 NVIC_ICER 这两个寄存器。

    3.编写中断服务函数

    在启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。

    展开全文
  • 理论基础 EX0口导通为1 中断嵌套 外部中断0是所有中断里面优先级最高的->INT0 单片机优先级 P3.2-P3.7都是和中断有关的I/O...中断函数的书写 void functionName()interrupt n { ... }//interrupt表示成中断服务函

    理论基础

    EX0口导通为1 
    中断嵌套
    外部中断0是所有中断里面优先级最高的->INT0
    单片机优先级	P3.2-P3.7都是和中断有关的I/O口
    INT0外部中断0>TO定时计数器0>INT1>T1
    

    在这里插入图片描述

    中断涉及的几个环节

    ①中断源           (前面提到的甲方)
    ②中断申请       (甲方发出信号提出申请)
    ③开放中断       (乙方同意传送)
    ④保护现场       (安排好当前的工作)
    ⑤中断服务       (响应乙方的要求)
    ⑥恢复现场       (完事后,回去……)
    ⑦中断返回       (继续做打断前的工作)
    

    中断响应条件

    1.中断源有中断请求;
    2.此中断源的中断允许位为1;
    3.CPU开中断(即EA=1)。
    

    以上三条同时满足时,CPU才有可能响应中断。


    一次中断过程的完整步骤

    中断请求
    中断使能->全局中断=0   外部中断=0、
    中断响应
    中断处理
    中断返回
    

    中断优先级的三条原则:

    1.CPU同时接收到几个中断时,首先响应优先级别最高的中断请求。
    2.正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。
    3.正在进行的低优先级中断服务,能被高优先级中断请求所中断。
    

    EA :全局中断使能位(总允许位)。

    =0:全局中断禁止;
    =1:全局中断允许。
    

    中断函数的书写

    void functionName()interrupt n
    {
    	...
    }//interrupt表示成中断服务函数,n是中断号,中断号是编译器识别不同中断的唯一编号
    

    中断函数与普通函数的区别

    不需要声明
    不能传参、
    不能直接调用中断函数,它是由硬件触发的
    




    实践部分

    下降沿触发

    独立按键部分默认先输入0X0F就是高电平,那么按下他就会实现高电平到低电平的下降沿从而触发中断
    

    低电平触发

    当按下独立按键的时候电平高转低,不松手的时候一直处于低电平,那么中断函数内的P2就会一直翻转,
    而由于反转速度过快,人眼无法识别,所以呈现的是全亮状态。
    

    外部中断

    INT0
    INT1
    
    /*********************************************************************************
    *实验名   :外部中断实验(低电平触发)
    *实验效果	:按住学习板上第三排任意按键 LED灯8位全亮
                  松开按键后 随机上4个或下4个灯亮
    *
    *********************************************************************************/
    #include<reg52.h>
    //按下独立按键的时候电平高转低,不松手的时候一直处于低电平,那么中断函数内的P2就会一直翻转,
        而由于反转速度过快,人眼无法识别,所以呈现的是全亮状态。
    void main()
    {
        P1=0X0F;//0000 1111	 前四个灯灭 后四个灯亮
    	P3=0X0F;//独立按键部分默认先输入0X0F就是高电平,那么按下他就会实现高电平到低电平的下降沿从而触发中断
    	EA=1;//全局中断打开
    	EX0=1;//INT0中断开启
    	IT0=0;//低电平触发
    	while(1)
    	{
    	    ;
    	}
    }
    
    void ISR_KEY()interrupt 0	 //中断服务函数
    {
        P1=~P1;
    }
    
    /*********************************************************************************
    *实验名   :外部中断实验(下降沿触发)
    *实验效果	:按下学习板上第三排任意按键,LED灯前后四位状态调换
    *
    *********************************************************************************/
    #include<reg52.h>
    //按一次就跳变,也就是说开始前四个灯不亮后四个亮,按下之后就反过来
    void main()
    {
        P1=0X0F;//0000 1111	 前四个灯灭 后四个灯亮
    	P3=0X0F;
    	EA=1;//全局中断打开
    	EX0=1;//INT0中断允许
    	IT0=1;//触发方式为下降沿触发
    	while(1)
    	{
    	    ;
    	}
    }
    
    void ISR_KEY()interrupt 0
    {
        P1=~P1;
    }
    
    EX0(IE.0),外部中断0允许位;
    ET0(IE.1),定时/计数器T0中断允许位;
    EX1(IE.2),外部中断0允许位;
    ET1(IE.3),定时/计数器T1中断允许位;
    ES(IE.4),串行口中断允许位;
    EA (IE.7), CPU中断允许(总允许)位。
    
    展开全文
  • 在 rt_hw_interrupt_disable() 函数里面需要依序完成的功能是: ; 1). 保存当前的全局中断状态,并把状态作为函数的返回值。 ; 2). 关闭全局中断。 ; r0 存储的数据就是函数的返回值。中断可以发生在 “MRS r0, ...
  • NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。 NVIC_Config()函数代码如下: static void NVIC_Config(void) /* 主要是配置中断源的优先级与打开使能中断...
  • 中断和查询方式区别

    千次阅读 2020-05-18 08:35:19
    处理流程复杂,函数嵌套执行的情况下,于处理不过来容易丢失事件。 CPU比作人,定时器比作闹钟的。 ①中断就相当于是人设定的时间到了闹钟自己响起的过程,此时人放下手中的事去做另一件事。 ②查询就是人发现自己有...
  • 在这里不得不提一下NVIC(嵌套向量中断控制器),它是内核里面的一个模块,属于Cortex-M7内核,但是RT1050的NVIC其实是Cortex-M7里标准NVIC的阉割版,是一个子集。虽然是阉割版,但是也是非常强大了,其中系统异常有...
  • FreeRTOS临界段的保护

    2021-02-01 21:29:08
    不带返回值的关中断函数,不能嵌套,不能在中断里面使用。不带返回值的意思是:在往 BASEPRI 写入新的值的时候,不用先将 BASEPRI 的值保存起来,即不用管当前的中断状态是怎么样的,既然不用管当前的中断状态,也就...
  • 今天同事问我, linux的中断可以嵌套吗?我说我也不知道啊, 印象中是cpu是可以中断嵌套的, 但是linux关掉了, 所以linux是不允许中断...直接开个vm, 把状态停到中断函数里面, 比如do_timer Breakpoint 1, do_timer (ti...
  • SAM4S NVIC的理解与分析

    千次阅读 2014-03-04 21:16:10
    发现了对DMA中断的处理理解有问题,关键的问题在于中断函数的重入,在配置NVIC寄存器的时候,不清楚是否会在中断函数未处理完成的情况下,会导致中断再次进入,引发中断嵌套,并且中断处理函数里面有很多全局变量。...
  • 学习RTOS(5)临界段

    2020-08-22 15:29:23
    什么是临界段 临界段用一句话概括就是一段在执行的时候不能被中断的代码段。那么什么情况下临界段会被...代码清单 8-2(1): 不带返回值的关中断函数,不能嵌套,不能在中断里面使用。不带返回值的意思是:在往 BASEPR
  • SDK中使用C进行OOP的实现,简单概括即使用了大量的结构体对变量、操作函数、中断函数进行层层嵌套。大体步骤如下: 1、定义UART的物理层参数结构体  首先需要定义一个结构体,包含实现底层串口驱动所需的所有函数、...
  • 对stm32的NVIC的理解

    2018-04-01 23:22:03
    首先它是嵌套的,意思就是cpu在接收一个中断,在处理这个中断的时候,可以被具有更高优先级的中断打断当前的执行顺序,跳到更高级的中断处理函数去执行里面的程序,执行完了,再返回执行前一个中断,执行完后,没有...
  • 以下场景假设都在函数内的循环里面:breakbreak语句用于终结本次的循环体,如果循环是嵌套的,终结所有嵌套的循环体。continuecontinue语句中断本次的循环体,如果循环是嵌套的,跳出本次循环体去执行外层的下一次...
  • for语句: for的另一种用法: while语句: ...while和if嵌套: ...1.在桌面(已设置桌面为工作空间)健一个后缀名为.m的文件,文件名与里面定义的函数名一致; 2.直接在MATLAB中用函数会显示...
  • 单的计算最大的中断嵌套层数,并在此基础上再增加些空间。另外要注意的是,RTX 的内核函数都是在 SVC 中断中调用的,用户也需要把这个考虑到系统栈大小里面,按照官方的说明,最小 128 字节,推荐 256 字节。 一般...
  • Excel_VBA教程

    2014-09-22 11:36:34
    4.在中断模式下使用立即窗口 269 5.使用STOP语句 271 6.添加监视表达式 271 7.清除监视表达式 274 8.使用快速监视 274 9.使用本地窗口和调用堆栈对话框 275 10.逐句运行VBA过程 276 11.逐句运行过程 277 12.逐过程...
  • EXCEL编程VBA高级教程

    2015-04-16 11:40:55
    第十一节过程和函数........................................................................................................................4 一.Sub过程....................................................
  • 为此我们给每个组件增加一个ApplicationLike类,里面定义了onCreate和onStop两个生命周期函数。 看到网上有个方案说:主项目负责加载组件,由于主项目和组件之间是隔离的,那么主项目如何调用组件ApplicationLike的...
  • 正则表达式

    2014-12-03 14:51:39
    注意,由于子表达式可以嵌套在其它子表达式中, 所以它的位置是被计数的左括号的位置. 例如:在下面的正则表达式被指定为 \2: /([Jj]ava([Ss]cript)) \sis \s (fun\w*) / 对正则表达式中前一子表达式的引用所...

空空如也

空空如也

1 2
收藏数 21
精华内容 8
关键字:

中断函数里面嵌套中断