八、EXTI外部中断

外部中断

中断系统是管理和执行中断的逻辑结构,外部中断是能产生中断的外设之一
中断:
在主程序运行过程中,出现了特定的中断触发条件(中断源)(对于外部中断来说,可以是引脚电平发生了变化,可以是定时时间到了,对于串口通信来说,可以是接收到了数据),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
使用中断系统可以极大的提高程序效率,若无中断系统,为了防止外部中断被忽略或串口数据被覆盖,主程序需要不断地查询是否有这类事件的发生,不能再干其他事了。(如无定时器中断,主程序只有依靠Delay函数才能实现定时的功能),有了中断系统主程序就可以放心执行其他事情,有中断时再处理,提高效率。
(就像是人睡觉使用闹钟一样,如果不定闹钟,就需要一直看手机有没有到起床时间,但定了闹钟之后,等到闹钟响了再起床,不用再一遍一遍的查看手机了。)

中断优先级:
当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。(优先级数值越小,优先级越高)

中断嵌套:
当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

可屏蔽中断通道(中断源):
STM32 中有68个可屏蔽中断通道(中断源),包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设(68个中断源是F1系列中最多的,而对于某个具体型号可能并没有这么多,所以中断源的数量以单片机的数据手册为准),这些中断源都使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。
STM32中断资源:

  1. 窗口看门狗,用来监测程序运行状态的中断(若程序卡死,未及时喂狗,窗口看门狗会申请中断,让程序跳到窗口看门狗的中断程序里,检查错误)
    2.PVD电源电压监测,若供电电压不足,PVD电路会申请中断,在中断中了解到供电不足,尽快保存重要数据
    (外设电路检测到什么异常或事件,需要提示CPU,申请中断,让程序调到对应中断函数运行一次。)
    中断向量在这里插入图片描述
    程序中的中断函数地址由编译器分配,不固定。(但因为硬件限制,中断只能跳到固定地址执行程序)为了让硬件跳转到一个不固定的中断函数里,在内存里定义一个地址的列表(固定),中断发生后就跳到这个固定位置,这里再由编译器加上一条跳转到中断函数的代码,这样中断就可以跳转到任意位置了。这个中断地址的列表就叫做中断向量。

NVIC嵌套中断向量控制器:
使用NVIC嵌套中断向量控制器(是内核外设)(是STM32用来管理中断、分配优先级的)统一管理中断,每个中断通道都拥有16个可编程的优先等级,为了处理不同形式的优先级,STM32的NVIC可以对这16个优先级进行分组,分为抢占优先级和响应优先级。
叫号系统,根据中断优先级分配中断的优先顺序。
在这里插入图片描述在这里插入图片描述
抢占优先级和响应优先级:
当前病人正在看病,若来了一个紧急病人,可以等上一个病人诊治完插队来看病,这个病人就具有响应优先级;当前病人正在看病,非常紧急的病人来临,中断当前病人的诊治,救治这个非常紧急的病人,这个病人就具有抢占优先级。(决定是否可以进行中断嵌套的优先级叫做抢占优先级,抢占优先级高可以进行中断嵌套。)
NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级,分组完成后,注意取值范围在这里插入图片描述
抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队,数值小的优先响应,中断号如下图的优先级一列。在这里插入图片描述

病人1:EXTI(Extern Interrupt)外部中断

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

支持的触发方式:上升沿/下降沿/双边沿/软件触发(引脚不变,程序代码触发中断)
支持的GPIO口:所有GPIO口,但相同的Pin(如PA0和PB0)不能同时触发中断
通道数:16个GPIO_Pin(0~15),外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
(外部中断可以从低功耗模式的停止模式下唤醒STM32,对PVD电源电压监测,当电源从电压过低恢复时,PVD需要借助外部中断退出停止模式;对RTC闹钟,为了省电,RTC定一个闹钟使STM32进入停止模式,等闹钟响时再唤醒,也需要借助外部中断,USB唤醒、以太网唤醒,都类似。)
触发响应方式:中断响应/事件响应
中断响应是当外部中断检测到引脚电平变化,引脚电平变化触发中断;
事件响应是STM32对外部中断增加的额外功能,当外部中断检测到引脚电平变化,选择触发事件,外部中断信号不通向CPU而通向其他外设,用其来触发其他外设的操作,如触发ADC转换、触发DMA等,属于外设之间的联合工作。

EXTI外部中断整体结构图
在这里插入图片描述
#1.最左边GPIO的外设(GPIOA、GPIOB、GPIOC……),每个GPIO外设有16个引脚,但EXTI模块只有16个GPIO的通道,若每个引脚占用一个通道,EXTI的16个通道不够用,#2.所以使用AFIO(数据选择器的作用)中断引脚选择电路模块,可以在多个GPIO外设的16个引脚选择一个连接到后面的EXTI通道里。因为PA0、PB0、PC0等经过AFIO选择之后,只有一个能接到EXTI通道0上,同理,PA1、PB1、PC1也只有一个能接到EXTI通道1上,故相同的Pin(如PA0和PB0)不能同时触发中断。#3.然后通过AFIO选择之后的16个通道就接到了EXTI边沿检测及控制电路上,同时下面4个蹭网的外设也并列接进来,这些加起来,就组成了EXTI的20个输入信号。#4.经过EXTI电路分为两种输出,上面的接到NVIC,用来触发中断,(20路的输入太多,占用NVIC的通道资源,将其中外部中断的95和1510分别分到了一个通道里,外部中断95会触发同一个中断函数,1510也会触发同一个中断函数,在编程中通过标志位区分到底是哪个中断进来的),下面的20条输出线路到了其他外设,用来触发其他外设操作的,也就是事件响应

AFIO复用IO口:在这里插入图片描述

1.AFIO主要用于引脚复用功能的选择和重定义 AFIO选择中断引脚的结构图
,就是数据选择器的作用。
2.在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择。
复用功能引脚重映射:用AFIO将默认复用功能引脚换到重定义的位置
在这里插入图片描述

AFIO选择中断引脚的结构图就是一系列的数据选择器,第一个输入是PA0、PB0、PC0……PG0,尾号都为0,然后通过数据选择器,最终选择一个连接到EXTI0上(上面写的是配置寄存器的这些位,就可以决定哪一输入)下面的EXTI……EXTI15也都是数据选择器

EXTI(外部中断/事件控制器)

在这里插入图片描述
右边是20根输入线,输入线进入边沿检测电路,在上面的上升沿寄存器和下降沿寄存器可以选择是上升沿触发、下降沿触发、或两个都触发,接着触发信号就进入一个或门的输入端。
硬件触发和软件中断寄存器的值接到或门上,任意一个为1,或门就输出为1。触发信号通过或门之后分为两路,上面的一路用于触发中断,下面的一路触发事件。触发中断首先会置一个挂起寄存器,相当于一个中断标志位,可以读取寄存器判断是哪个通道触发的中断,如中断挂起寄存器置1,就会继续往左走,和中断屏蔽寄存器共同进入一个与门,这里的与门是开关的作用(对与门来说,1与任何数x都等于这个任意数x,0与任何数x都等于0,相当于中断屏蔽寄存器给1,另一个输入就直接输出,允许中断;中断屏蔽寄存器给0,另一个输入无论是什么都输出0,相当于屏蔽了这个中断)然后至NVIC中断寄存器。下面的一路首先也是一个事件屏蔽寄存器进行开关控制,最后通过一个脉冲发生器到其他外设。(这个脉冲发生器就是给一个电平脉冲,用来触发其他外设的动作)
图中的/20就是20根线,代表20个通道。图中上部分就是外设接口和APB总线,可以通过总线访问这些寄存器。
在这里插入图片描述
或门:输入只要有一个为1,输出为1;
输入全为0,输出才为0。
与门:输入只要有一个为0,输出为0;
输入全为1,输出才为1。
非门:输入为1,输出0;
输入为0,输出1.
在这里插入图片描述

数据选择器:侧面有选择控制端,根据控制端的数据,从输入选择一个接到输出

旋转编码器
在这里插入图片描述在这里插入图片描述
内部用金属触点进行通断,是一种机械触点式编码器,左右是两部分开关触点。中间圆的金属片是按键,按键的轴按下,上面的两根线短路,松手上面的两根线断开

编码盘在这里插入图片描述在这里插入图片描述
一系列像光栅一样的东西,是金属触点,在旋转时,依次接通和断开两边的触点,这个金属盘的位置也经过设计,可以让两侧触点的通断产生一个90度的相位差,配合外部电路,这个编码器的两个输出(蓝色圈住的部分)输出相差90度相位的波形。在这里插入图片描述
旋转编码器的硬件电路在这里插入图片描述
中间是旋转编码器,上面的两个引脚悬空。内部的两个触点在旋转轴旋转时以相位差相差90度的方式交替导通,这个开关信号配合外围电路输出高低电平。左边接一个10k的上拉电阻,默认没旋转的时候将这个点上拉为高电平,通过此点输出到A端口也是高电平;当旋转时,内部触点导通,这个点被拉到GND,再通过R3输出,A端口就是低电平了。(R3是输出限流电阻,防止模块引脚电流过大;C1是输出滤波电容,防止一些输出信号抖动)
旋转编码器模块接线图在这里插入图片描述

使用外部中断的配置

在这里插入图片描述
配置外部中断,将外部中断从GPIO到NVIC这一路中出现的外设模块(如RCC、GPIO、AFIO、EXTI、NVIC)都配置好
1.配置RCC,将涉及的外设时钟都打开,弄清楚外设接在哪个总线上(其中EXTI和NVIC外设的时钟是一直都开着的,不用再开启。NVIC外设是内核外设,内核外设不用开启时钟,RCC只管理内核外的外设)
2.配置GPIO,选择端口为输入模式,当外设使用GPIO不知道配置为什么模式时参考手册里的外设的GPIO配置表(每个外设的各个引脚需要配置什么模式)
3.配置AFIO,选择用的GPIO,外部中断引脚选择配置连接到后面的EXTI
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//用于配置AFIO的数据选择器,选择想要的中断引脚。参数1:选择GPIOx外设作为外部中断源;参数2:指定要配置的外部中断线。
执行函数后,AFIO的第14个数据选择器就拨好了:输入端被拨到了GPIOB外设上,对应PB14号引脚;输出端固定连接EXTI的第14个中断线路,这样PB14号引脚电平信号可以顺利通过AFIO,进入到后级EXTI电路
4.配置EXTI,选择边缘触发方式(如上升沿、下降沿、双边沿),选择触发响应方式(中断响应、事件响应)
5.配置NVIC,给中断选择合适的优先级。
最后,通过NVIC外部中断信号就可以进入CPU了,CPU接收到中断信号,跳转到中断函数里执行中断程序

GPIO外设的中断函数:
void GPIO_AFIODeInit(void);//复位AFIO外设,调用此函数,AFIO的配置就会全部清除
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//用于锁定GPIO配置,调用此函数,参数指定引脚的配置被锁定,防止意外更改
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);
//这两个函数用于配置AFIO的事件输出功能
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);//用于进行引脚重映射,参数1:引脚重映射方式;参数2:新状态
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//用于配置AFIO的数据选择器,选择想要的中断引脚
EXTI的库函数:
void EXTI_DeInit(void);
//清除EXTI配置,恢复成上电默认状态
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
//根据EXTI_InitStruct结构体里的参数配置EXTI外设,初始化EXTI重要函数,使用方法GPIO_Init()一样
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
//将参数传递的结构体变量赋成默认值

这前三个函数基本每个外设都需要这些类型的函数,这些模板函数使用方法和意思也都一样,外部中断、定时器、ADC、串口都是使用结构体初始化的方式,结构体可以看到参数名字,参数也都是复制粘贴来的,不用查看寄存器,选选参数就配置好了

void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
//软件触发外部中断,调用此参数,给参数指定中断线,就可软件触发一次此外部中断。若只需要外部引脚触发中断就不用这个函数。

下面的四个参数也是库函数的模板函数,很多模块都有这四个函数,在外设运行时会产生一些状态标志位(如外部中断到来,会有一个挂起寄存器置一个标志位,对于其他外设,如串口接收到数据,会置标志位,定时器时间到也会置标志位,这些标志位都放在状态寄存器里),当程序想要查看这些标志位时就可以用到下面的四个函数:
想在主程序中查看和清除标志位,用这两个函数:

FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);//获取指定标志位是否被置1
void EXTI_ClearFlag(uint32_t EXTI_Line);//对置1的标志位进行清除

有的标志位比较紧急,在置标志位后会触发中断。
想在中断函数里想查看标志位和清楚标志位,用下面两个函数:

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); //获取中断标志位是否被置1
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);//清除中断挂起标志位

这四个函数都是对状态寄存器的读写

NVIC这个内核外设相关函数:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
//在配置前指定中断分组,配置优先级分组(从占(响应)优先级和先占(抢占)优先级)参数是中断分组的方式
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
//根据结构体里指定的参数初始化NVIC
只需要用上面的两个函数配置NVIC。
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
//设置中断向量表
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
//系统低功耗配置

NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;在这里插入图片描述
md.s启动文件中以IRQHandler结尾的字符串就是中的函数的名字在这里插入图片描述

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值