嵌入式软件开发学习三:中断

Tips:

        资料来源:[5-1] EXTI外部中断_哔哩哔哩_bilibili

一、什么是中断?

        中断是计算机系统中的一个重要机制,用于在程序执行过程中响应外部事件。中断机制允许CPU暂停当前正在执行的任务,转而处理更高优先级的事件,处理完成后返回到被中断的任务继续执行。这种机制对于提高系统的响应速度和效率至关重要。

        Tips:中断响应是非常快非常迅速的,基本不会影响主程序的正常运行。当然因此中断当中放进延时函数是大忌。

STM32的中断:  

        68个可屏蔽中断通道,包含EXTITIMADCUSARTSPII2CRTC等多个外设。

        使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。

中断可以按照不同的标准进行分类,常见的分类方式如下:

按照来源分类:

  1. 硬件中断(硬中断)

    • 这类中断是由外部硬件设备触发的,例如键盘按下键、磁盘完成读写操作等。
    • 硬件中断通常通过专门的中断控制器管理,并通过中断请求线(IRQ)向CPU发出信号。
    • 硬件中断可以进一步细分为可屏蔽中断(Maskable Interrupts)和非屏蔽中断(Non-Maskable Interrupts)。
      • 可屏蔽中断可以在某些情况下被操作系统禁止或延迟处理。
      • 非屏蔽中断则总是会被立即处理,通常用于紧急情况,如电源故障。
  2. 软件中断(软中断)

    • 软中断是由软件指令触发的中断,如除法错误、非法指令等。
    • 软中断也可以是操作系统为了执行特定任务(如调度进程)而故意触发的。
    • 在某些系统中,软件中断可以用来模拟硬件中断的功能。

按照处理方式分类:

  1. 同步中断

    • 这种中断是在指令执行期间由处理器内部产生的,如算术溢出。
    • 同步中断通常是由于执行了一条特定的指令而引发的。
  2. 异步中断

    • 异步中断可以在任何时刻发生,与当前正在执行的指令无关。
    • 异步中断通常是由外部硬件设备触发的,如定时器中断或外部设备完成数据传输。

中断处理流程:

  1. 中断请求:硬件设备通过中断控制器向CPU发送中断请求。
  2. 中断响应:CPU保存当前上下文(寄存器状态等),并跳转到预定义的中断服务程序。
  3. 中断服务:中断服务程序执行必要的处理,如读取设备状态、更新内存中的数据等。
  4. 中断返回:中断服务程序执行完毕后,CPU恢复被中断前的状态,继续执行原来的任务。

        中断机制是现代操作系统和嵌入式系统的核心部分之一,它使得系统能够高效地处理各种事件和故障,从而保证了系统的稳定性和可靠性。

 中断优先级:

        中断优先级是指在一个系统中有多个中断源时,根据中断的重要程度或紧急程度对其进行排序的一种机制。当多个中断同时发生时,具有较高优先级的中断将被优先处理。中断优先级的管理有助于避免低优先级中断长时间占用CPU资源,从而导致高优先级中断无法及时响应的情况。

中断优先级的实现

  • NVIC (Nested Vectored Interrupt Controller):在ARM Cortex-M系列微控制器中,NVIC控制器负责管理中断优先级。
  • ISR (Interrupt Service Routine):每个中断都有一个对应的中断服务程序,用于处理中断事件。
  • 抢占优先级和响应优先级:在STM32等微控制器中,中断优先级分为抢占优先级和响应优先级两个维度。
    • 抢占优先级决定了中断是否可以打断另一个正在执行的中断服务程序。
    • 响应优先级决定了同优先级中断之间的执行顺序。
  • 优先级分组:可以通过配置NVIC来决定抢占优先级和响应优先级之间的分配比例。

二、NVIC中断优先级管理器

        NVIC (Nested Vectored Interrupt Controller) 是一种嵌套向量中断控制器,它主要用于 ARM Cortex-M 系列微控制器中,负责管理和控制中断请求。以下是关于 NVIC 的一些关键点:

  • 功能: NVIC 负责中断的管理和调度,使得处理器能够响应外部或内部事件而暂停当前的任务,并转去执行相应的中断服务程序(ISR)来处理这些事件。
  • 嵌套: 当一个高优先级的中断请求在另一个中断服务程序执行期间到来时,NVIC 可以安排高优先级中断嵌套到当前正在处理的中断之中,从而提高系统的响应速度。
  • 向量: 每个中断都有一个与之关联的中断向量,这个向量指向中断服务程序的入口地址。当处理器接收到中断请求时,它会根据中断向量跳转到正确的 ISR 地址。
  • 可编程: NVIC 是完全可编程的,可以通过软件配置不同的中断优先级,使某些中断比其他中断更优先得到处理。
  • 数量: NVIC 支持多达 32 个中断源(IRQ[31:0]),每个中断源可以被分配不同的优先级。
  • 优先级: NVIC 支持多个优先级级别,允许开发者根据应用程序的需求来调整中断的响应顺序。

        NVIC 在现代嵌入式系统设计中扮演了重要的角色,因为它可以帮助开发者有效地管理中断,优化系统的实时性能。

NVIC基本结构

NVIC优先级分组 

        NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为n位的抢占优先级4-n位的响应优先级

        抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

三、EXTI(Extern Interrupt)外部中断

        EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

        支持的触发方式:上升沿/下降沿/双边沿/软件触发

        支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断

        通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒

        触发响应方式:中断响应(申请中断,让CPU去执行中断函数)/事件响应(中断信号通向外设,触发其他操作,例如ADC转化or DMA等)

四、中断例程

功能效果:

        通过红外反射传感器/红外对射传感器等响应式传感器,触发中断,并执行中断函数。

例程代码:

/**
  * 函    数:计数传感器初始化
  * 参    数:无
  * 返 回 值:无
  */
void CountSensor_Init(void)
{
    /*开启时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);		//开启AFIO的时钟,外部中断必须开启AFIO的时钟
    
    /*GPIO初始化*/
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);						//将PB14引脚初始化为上拉输入
    
    /*AFIO选择中断引脚*/
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
    
    /*EXTI初始化*/
    EXTI_InitTypeDef EXTI_InitStructure;                        //定义结构体变量
    EXTI_InitStructure.EXTI_Line = EXTI_Line14;					//选择配置外部中断的14号线
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;					//指定外部中断线使能
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			//指定外部中断线为中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;		//指定外部中断线为下降沿触发
    EXTI_Init(&EXTI_InitStructure);                             //将结构体变量交给EXTI_Init,配置EXTI外设
    
    /*NVIC中断分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//配置NVIC为分组2
                                                                //即抢占优先级范围:0~3,响应优先级范围:0~3
                                                                //此分组配置在整个工程中仅需调用一次
                                                                //若有多个中断,可以把此代码放在main函数内,while循环之前
                                                                //若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
    
    /*NVIC配置*/
    NVIC_InitTypeDef NVIC_InitStructure;						//定义结构体变量
    NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;		//选择配置NVIC的EXTI15_10线
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//指定NVIC线路使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定NVIC线路的抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure);                             //将结构体变量交给NVIC_Init,配置NVIC外设
}

/**
  * 函    数:获取计数传感器的计数值
  * 参    数:无
  * 返 回 值:计数值,范围:0~65535
  */
uint16_t CountSensor_Get(void)
{
    return CountSensor_Count;
}

/**
  * 函    数:EXTI15_10外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void EXTI15_10_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line14) == SET)		//判断是否是外部中断14号线触发的中断
    {
        /*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
        {
            CountSensor_Count ++;					//计数值自增一次
        }
        EXTI_ClearITPendingBit(EXTI_Line14);		//清除外部中断14号线的中断标志位
                                                    //中断标志位必须清除
                                                    //否则中断将连续不断地触发,导致主程序卡死
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值