【第五章 EXTI 外部中断】
[5-1] EXTI外部中断
[5-2] 对射式红外传感器计次&旋转编码器计次

引言

目前正处于学习江协STM32,自己想根据学习的内容进行一个总结,也是方便时间一长用于回顾,以方便形成一个整体的框架,也希望能够提供给大家看,同时能够查漏补缺,不正确的地方也希望大家指正。


一、外部中断和中断系统

中断系统是管理和执行中断的逻辑结构,外部中断是众多能产生中断的外设之一,本章借外部中断→(学)中断系统。

1、什么是中断?
在主程序运行过程中,出现了特定的中断触发条件(即中断源),使CPU暂停当前主正在运行的主程序,转而处理中断程序,处理完成后又返回原来被暂停位置主程序,继续运行。

⭐⭐⭐对于外部中断来说,中断时引脚发生了电平跳变;对定时器来说,定时时间到了;对串口来说,可以是接收到了程序。

2、中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。(注:优先级是由自己设置)
在这里插入图片描述

3、中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而处理新的中断程序,处理完后依次进行返回。
在这里插入图片描述

二、STM32中断

1.基础知识

1、STM32有68个可屏蔽中断通道,有EXTI(外部中断)、TIM(定时器)、ADC(模拟器转换)、USART(串口)、SPI和I2C(通信)、RTC(实时时钟)等外设。
2、使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进一步分组,进一步设置抢占优先级和响应优先级。

2.中断实现过程

1、实现EXTI中断基本结构
在这里插入图片描述
2、具体实现
基本流程,根据EXTI基本结构写代码
1.配置RCC时钟,启动相应的GPIO和AFIO。EXTI和NVIC是内核外设,不需要开启RCC时钟,这两个的时钟是一直开着的状态,RCC只管内核的外设。

实列代码:

//先是开启GPIOB和AFIO的外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

2.配置GPIO口
初始化 GPIOB 端口的第 14 号引脚

实例代码

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);

3.配置AFIO
AFIO是一个数据选择器,主要是在前面n个GPIO口中挑选一个到EXTI程序中。(即多个输入一个输出)
在STM32中,AFIO主要有两个任务:①、复用功能引脚重映射 ②、中断引脚选择
在这里插入图片描述
GPIO_EXTILineConfig功能为配置AFIO的数据选择器来配置我们想要的中断引脚。配置的是14号引脚。

//第三步:配置AFIO(在库的_gpio中找定义)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);

4.配置EXTI
EXTI简介:

  • EXTI(Extern Interrupt)外部中断
  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC(CPU的小助理)发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发
  • 支持的GPIO口:所有的GPIO口,但相同的Pin不能同时触发中断(因为AFIO与EXTI的接口只有十六个,AFIO只能从众多GPIO的接口中挑选一个来接入EXTI,比如像PA0,PB0,PC0不能够同时使用)
  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应/事件响应
EXTI_InitTypeDef EXTI_InitStructure;	EXTI_InitStructure.EXTI_Line=EXTI_Line14;    //要配置的中断线,与所选的pin口相关联
EXTI_InitStructure.EXTI_LineCmd=ENABLE;    //指定中断线的新状态,开启中断
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;    //指定外部中断线的模式:中断模式和事件模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;     //指定触发信号的有限边沿
EXTI_Init(&EXTI_InitStructure);

5.配置NVIC
NVIC优先级管理,主要进行进行中断分配,NVIC只有一个输出口,根据中断的优先级来告诉CPU来先进行那个中断处理

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //函数中断分组
NVIC_InitTypeDef NVIC_InitStructure;   //定义结构
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;    //中断通道开启或者关闭,参数可以是IRQn_Type里面的值
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;      //指定中断中是使能还是失能;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;   //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;    //响应优先级
NVIC_Init(&NVIC_InitStructure);

3.注意事项

在stm32中中断函数是固定的,每个中断通道对应一个中断函数,如果写错了中断函数的名字就会进不了中断。

                DCD     EXTI1_IRQHandler           ; EXTI Line 1
                DCD     EXTI2_IRQHandler           ; EXTI Line 2
                DCD     EXTI3_IRQHandler           ; EXTI Line 3
                DCD     EXTI4_IRQHandler           ; EXTI Line 4
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10

其中有一些是共用的(9_5和15_10各自分别分配到了一个通道里,器触发分别各自相同的中断函数,需要根据标志位区分到底那个中断进来),所以要进行中断标志位的判断,确保是我们想要的中断源进入中断函数。

列如:EXTI_GetFlagStatus(EXTI_Line14)==SET,判断是不是EXTI14进入了中断标志位。

在中断结束后一定要清除中断标志位,不然中断标志位置1后会一直申请中断。

//中断函数的名字是固定的,要在startup_stm32f10x_md.s中寻找,看到定义的中断向量表
void EXTI15_10_IRQHandler(void)
{
	//中断函数中先进行一个中断标志位的判断,确保是我们想要的中断源触发的函数
	if(EXTI_GetITStatus(EXTI_Line14)==SET)
	{
		 // 延时10ms消抖
     Delay_ms(10);   // 需要实现精确延时函数
        
     // 再次检查引脚电平,确保是稳定的高电平(假设遮挡为高,DO遮挡时时高电平)
     if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 1)
     {
			 CountSensor_count++;
     }
		 
		 
		EXTI_ClearITPendingBit(EXTI_Line14);  //启动标志位后一定要清除,因为不清除的话,一直会中断,死循环
	}
}

总结

暂时未写,后续补充。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐