P11-EXTI外部中断-1.jpg

P11-EXTI外部中断.jpg

INIT

INIT.jpg

INIT:本节内容正式开始。action!

引言-观察本节的程序实验现象

本节我们来学习STM32的外部中断和中断系统。

首先我们看一下本节课程序的现象,本节课有两个程序,第一个是对射式红外传感器计次,第二个是旋转编码器计次。

实验一:对射式红外传感器计次 实验现象

我们先看一下第一个程序现象,

图:程序一:对射式红外传感器计次

P11-EXTI外部中断.png

这里接了一个红外对管的传感器,OLED显示了一个数字,现在是000。我们用挡光片挡在这个红外对管中间,此时这个模块的输出指示灯灭了,代表现在输出高电平。

图:用挡光片挡在这个红外对管中间,此时这个模块的输出指示灯灭了

P11-EXTI外部中断-2.png

然后再拿开挡光片,此时输出指示灯亮了,在灭到亮之间会产生一个下降盐,这个下降沿触发单片机引脚的外部中断,然后执行数字加1的中断程序,所以现在屏幕就显示到001。

图:下降沿触发单片机引脚的外部中断,然后执行数字加1的中断程序,所以现在屏幕就显示到001。

P11-EXTI外部中断-1.png

那我们再挡光几次。屏幕上的数字就对我们挡光的次数进行了统计,这就是第一个程序的现象。

实验二:旋转编码器计次 实验现象

图:初试状态

P11-EXTI外部中断-5.png

图:向左旋转编码器,OLED上的数字增加

P11-EXTI外部中断-4.png

图:向右旋转编码器,OLED上的数字减小

P11-EXTI外部中断-3.png

好,那我们来看一下本节的知识点。本节课要讲的是STM32的中断系统和外部中断。中断系统是管理和执行中断的逻辑结构,外部中断是众多能产生中断的外设之一,所以本节我们就借助外部中断来学习一下中断系统。在以后学其他外设的时候也是会经常和中断打交道的。

那我们先来了解一下中断的概念。

中断系统

1、中断:

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

2、中断优先级:

当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

3、中断嵌套:

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

中断的定义

首先中断的定义,是在主程序运行过程中出现了特定的中断触发条件,这个中断触发条件就是中断源,那使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。

可以看出来,中断就是在正常主程序执行的某个时刻发生了中断触发条件。比如对于外部中断来说,可以是引脚发生的电平跳变。对于定时器来说,可以是定时时间到了。对于串口通信来说,可以是接收到的数据。

当这些事件发生时,情况会比较紧急,比如外部中断来了,你如果不来处理,下一个跳变信号就跟着过来了。比如串口接收中断来了,如果你不来读取接收到的数据,那下一个数据再过来就会把原来的数据覆盖掉了。

所以我们希望当中断条件满足时,CPU能够立即停下当前执行的程序,转而去处理这些中断事件的程序。比如外部中断来了,我想要计次,那就变量++。串口中断来了,我就把接收到的数据转存起来。当这些紧急事件处理完成后,CPU还能回到原来停下的地方继续运行,这就是中断的处理流程和用途,使用中断系统能够极大的提高程序的效率。

比如如果没有终端系统,为了防止外部中断被忽略或者串口数据被覆盖,那主程序就只能不断的查询是否有这些事件发生,不能再干其他事情了。

比如如果没有定时器中断,那主程序只有Delay函数才能实现定时的功能。但有了中断系统之后,主程序就可以放心执行其他事情,有中断的时候再去处理,这样效率就会大大提升。

💡单片机不能没有中断系统!

这就好像你早上定了一个闹钟,定好之后就可以放心睡觉了。时间到了闹钟会提醒你,就相当于产生了一个中断信号。如果你没有闹钟,那你就得不断的看时间,生怕错过了起床点,那这样你就没法安心睡觉了,是吧?

中断优先级

接着我们来看一下中断优先级,它是当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源。

也就是说中断优先级就是中断的紧急程度。这个中断优先级是我们根据程序设计的需求自己设置的。中断优先级是为了在多个中断同时申请时判断一下应该先处理哪个。

如果事件非常紧急,那你就把优先级设置高一些。如果不是那么紧急,那你就可以把优先级设置低一些。这样可以更好的安排这些中断事件,防止紧急的事件被别的中断耽误。

在STM32中中断优先级还有多种分类,这个我们等会儿再详细讲。

中断嵌套

然后我们再看一下下面一个概念,中断嵌套。它是当一个中断程序正在运行时,又有新的更高优先级的中断申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。

这种把中断程序再次中断的现象就叫做中断嵌套。中断嵌套也是为了照顾非常紧急的中断的。如果现在CPU已经在执行某个中断程序了,这时又发生了一个非常紧急的中断,那这个中断就可以把当前的中断程序进行二次中断,这样新的紧急中断就可以立即被执行了。

那能否进行中断嵌套也是由中断优先级来决定的。这个等会儿再细说。

中断流程图

然后我们看一下这几个中断的执行流程图。

中断程序的执行流程

第一个是中断程序的执行流程。

图:中断程序的执行流程。

P11-EXTI外部中断-6.png

左边是主程序,当它执行到某个地方时,外设的中断条件满足了。那这时无论主程序在干什么事情,比如加减乘除还没算完,OLED显示程序才执行一半,Delay函数还正在等待。中断来了,主程序都得立即暂停程序,由硬件电路自动跳转到中断程序中。

当中断程序执行完之后,程序在返回被暂停的地方继续运行。比如加减乘除没算完,现在就可以继续算了。OLED没显示完,现在就继续显示,Delay没延时完,现在就继续延时。

那这个被暂停的地方我们就称它为断点。为了程序能在中断返回后继续原来的工作。在中断执行前会对程序的现场进行保护,中断执行后会再还原现场,这样可以保证主程序即使被中断了,回来之后也能继续运行。

当然我们用C语言编程,保护现场和还原现场的工作并不需要我们来做,编译器自动帮我们做好了,所以这里了解一下即可。

中断嵌套的执行流程

接着中间这个图就是中断嵌套的执行流程。

图:中断嵌套的执行流程

P11-EXTI外部中断-7.png

比如这里就是正常的中断程序,当这个中断正在执行时,又有新的优先级更高的中断,那这里就会再次打断,然后执行新的中断,新的中断结束,再继续原来的中断,原来的中断结束再继续主程序,这就是中断嵌套的执行流程。

带有中断的程序

最后看一下右边的C语言程序,带有中断的程序就是这个样子的。

图:带有中断的程序

P11-EXTI外部中断-8.png

上面是主函数,while(1)死循环里就是主程序。

正常情况下程序就是在主程序里不断循环执行,当中断条件满足时,主程序就会暂停,然后自动跳转到中断程序里运行。中断程序顺序执行完之后,再返回主程序继续执行。

一般中断程序都是在一个子函数里的,这个函数不需要我们调用。当中断来临时由硬件自动调用这个函数,这就是在C语言程序中中断的执行流程。

了解完中断的概念,我们就来看一下STM32的终端。

STM32中断

STM32中断的概念

1、68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设

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

第一条是68个可屏蔽中断通道,这个中断通道就是中断源的意思,68个中断源这个是F1系列最多的中断数量。对于一个具体的型号可能没有这么多中转,所以这个数量看看就行,具体以对应型号的数据手册为准。

接着STM32的中断包含EXTI外部中断、TIM定时器、ADC模数转换器、USART串口、SPI通信、I2C通信、RTC实时时钟等多个外设。

通过这一句我们知道STM32的中断是非常多的,几乎所有的模块都能申请中断。

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

这个NVIC就是STM32中用来管理中断分配优先级的。NVIC的中断优先级总共有16个等级,还可以设置抢占优先级和响应优先级,这个是非常灵活的。

STM32里的中断资源

这个图就是STM32里的中断资源。

图:STM32里的中断资源

P11-EXTI外部中断-9.png

内核的中断

这里看一下,上面这些灰色的是内核的中断。

比如第一个复位中断,当产生复位事件时,程序就会自动执行复位中断函数,也就是我们复位后程序开始执行的位置。

然后NMI不可屏蔽中断、硬件失效、存储管理、总线错误、错误应用等等,这些都是内核里面的。

一般这些中断都比较高层,我们看上去也挺难理解的。但是这些中断我们一般用不到,所以了解一下即可。

STM32外设的中断

然后下面这些不是灰色的部分,就是STM32外设的中断了。

窗口定时器中断

比如第一个窗口看门狗,这个是用来监测程序运行状态的中断。比如你程序卡死了,没有及时喂狗,窗口看门狗就会申请中断,让你的程序调到窗口看门狗的中断程序里。那你在中断程序里就可以进行一些错误检查,看看出现什么问题了。

连到EXTI的电源电压检测(PVD)中断

然后PVD电源电压监测,如果你供电电压不足,PVD电路就会申请中断。你在中断里就知道现在供电不足,是不是电池没电了,赶紧保存一下重要数据。

接着下面这些也都是类似的功能,外设电路检测到有什么异常或者事件需要提示一下CPU的时候,它就可以申请中断,让程序跳到对应的中断函数里运行一次,用来处理这个异常或事件。

EXTI中断

那下面这个EXTI0到EXTI4(EXTI线0中断~EXTI线1中断),然后下面的EXTI9_5(EXTI线[9:5]中断)和最右边的EXTI15_10(EXTI线[15:10]中断),就是我们本节要学的外部中断对应的中断资源。

中断的地址(中断向量表)

然后这个表右边这里还有个中断的地址,这个地址是干什么的呢?

这个是因为我们程序中的中断函数,它的地址是由编译器来分配的,是不固定的。但是我们的中断跳转由于硬件的限制,只能跳到固定的地址执行程序。所以为了能让硬件跳转到一个不固定的中转函数里,这里就需要在内存中定义一个地址的列表,这个列表地址是固定的,中断发生后就跳到这个固定位置。

然后在这个固定位置,由编译器再加上一条跳转到中断函数的代码,这样中断跳转就可以跳到任意位置了。

这个中断地址列表就叫中断向量表,相当于中断跳转的一个跳板。不过我们用C语言编程的话,是不需要管这个中断向量表的。因为编译器都帮我们做好了,所以我们还是很省心的。

NVIC的基本结构

P11-EXTI外部中断.gif

🕺NVIC他来了!他就是CPU的小助手。

然后接下来我们来看一下NVIC的基本结构,这个NVIC的名字叫做嵌套中断向量控制器。在STM32中它是用来统一分配中断优先级和管理中断的。NVIC是一个内核外设,是CPU的小助手。

我们刚才看到了STM32的中断非常多,如果把这些中断全都接到CPU上,那CPU还得引出很多线进行适配,设计上就很麻烦了。并且如果很多中断同时申请,或者中断很多产生了拥堵,CPU也会很难处理。毕竟CPU主要是用来运算的,中断分配的任务就放到别的地方。所以NVIC就出现了。

图:NVIC的基本结构

P11-EXTI外部中断-10.png

NVIC有很多输入口,你有多少个中转线路都可以接过来。比如这里可以接到EXTI、TIM、ADC、USART等等,这里线上画了个斜杠,上面写个n,这个意思是一个外设可能会同时占用多个中断通道,所以这里有n条线。

然后NVIC只有一个输出口,NVIC根据每个中断的优先级分配中断的先后顺序之后,通过右边这一个输出口告诉CPU你该处理哪个中断。

对于中断先后顺序分配的任务,CPU不需要知道。

我们用一个例子来说明NVIC和CPU的关系

所以举个例子,比如这个CPU是一个医生,如果医院只有医生的话,当看病的人很多时,医生就得安排一下,先看谁后看谁。如果有紧急的病人,那还得让紧急的病人最先来。这个安排先后次序的任务很繁琐,会影响医生看病的效率,所以医院就安排了一个叫号系统,来病人统一取号,并且根据病人的等级分配一个优先级。然后叫号系统看一下现在在排队的病人,优先叫号紧急的病人。最后叫号系统给医生输出的就是一个一个排好队的病人,医生就可以专心看病了。

这个叫号系统在STM32里就是NVIC。

NVIC优先级分组

然后我们看一下中断的分组,为了处理不同形式的优先级,STM32的NVIC可以对优先级进行分组,分为抢占优先级和响应优先级。

那这两种形式的优先级有什么区别呢?

我们还来看一下病人叫号的这个例子。

响应优先级:

对于紧急的病人,其实有两种形式的优先。一种是上一个病人在看病,外面排队了很多病人。当上一个病人看完后,紧急的病人即使是后来的也会最先进去看病。这种相当于插队的优先级的就叫响应优先级,响应优先级高的可以插队提前看病。

抢占优先级:

另外如果这个病人更加紧急,并且此时已经有人在看病了,那他还可以不等上一个人看完,直接冲到医生的屋里,让上一个病人先靠边站,先给他看病,等他看完了上一个病人再继续,然后上一个病人结束了叫号系统再看看有没有人来,这种形式的优先级就是我们之前讲的中断嵌套,这种决定是不是可以中断嵌套的优先级就叫抢占优先级。抢占优先级高的可以进行中断嵌套。

为什么优先级要分组?

我们刚才说了每个中断有16个优先级,为了把这个优先级再区分为抢占优先级和响应优先级,就需要对这16个优先级进行分组了。

PPT

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

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

我们看一下PPT的第一句,NVIC的中断优先级由优先级寄存器的四位决定。这里4位二进制可以表示0到15的数,对应16个优先级,这个优先级的数是值越小优先级越高,0就是最高优先级。

这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级。

然后下面这一句,抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队。这个通过刚才的例子应该就好理解了。

然后还有抢占优先级和响应优先级均相同的,按中断号排队。这个中断号就是这里这个表里的这个数字。当抢占优先级和响应优先级均相同时,就按照这里的这个数字来排队。数值小的优先响应,所以STM32的中断不存在先来后到的排队方式,在任何时候都是优先级高先响应。

优先级的分组表

然后看一下下面的这个表,因为优先级总共是4位,所以就有(0,4)、(1,3)、(2,2)、(3,1)、(4,0)这5种分组方式。

图:

P11-EXTI外部中断-11.png

分数0就是0位的抢占等级取值只能为0,4位的响应等级取值可以是0到15,分组1是1位的抢占等级取值是0到1,3位的响应等级取值是0到7,然后分组2、3、4,都是按照这个规律来分配的。

大家自己看一下,这个分组方式在程序中是我们自己来选择的。选好分组方式之后,我们在配置优先级的时候,就要注意抢占优先级和响应优先级的取值范围了,不要超出这个表里规定的取值范围。

了解完NVIC这个叫号系统和叫号的规则,我们就来看一下第一个病人EXTI外部中断。

EXTI简介

PPT

1、EXTI(Extern Interrupt)外部中断

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

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

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

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

6、触发响应方式:中断响应/事件响应

1、 EXTI(Extern Interrupt)外部中断

先看一下第一条,EXTI它是Extern Interrupt的缩写,意思是外部中断。

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

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

这就是EXTI的基本功能。简单来说就是引脚电平变化,申请中断。

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

然后看一下触发方式。

EXTI支持引脚电平的变化类型为上升沿,就是电平从低电平变到高电平的瞬间触发中断。

下降沿就是高电平变到低电平的瞬间触发中断。

双边沿就是上升沿和下降沿都可以触发中转。

另外还支持软件触发,就是引脚啥事没有,程序里执行一句代码就能触发中断。

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

接着再看一下外部中断支持的GPIO口,它支持所有的GPIO口,也就是任意的GPIO口都可以当做外部中断的引脚。但相同的Pin不能同时触发中断。

这个意思就是比如PA0和PB0不能同时用,或者PA1、PB1、PC1这样的端口GPIO_Pin一样的,只能选1个作为中断引脚。所以你如果有多个中断引脚,要选择不同Pin的引脚,比如PA6和PA7,PA9和PB15,PB0和PB1这样的都可以。

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

然后再看一下外部中断占用的通道,其中有16个GPIO_Pin,这就对应GPIO_Pin_0到GPIO_Pin_15,外加PVD输出,RTC闹钟、USB唤醒、以太网唤醒,这些加起来总共有20个中转线路。

这里的16个GPIO_Pin是外部中断的主要功能,后面跟着的这四个东西其实是来"蹭网"的。为啥这些东西要来外部中断“蹭网”呢?因为这个外部中断有个功能,就是从低功耗模式的停止模式下唤醒SDM32。

那对PVD电源电压监测,当电源从电压过低恢复时,就需要PVD借助一下外部中断退出停止模式。

对于RTC闹钟来说,有时候为了来省电,RTC定一个闹钟之后,STM32会进入停止模式,等到闹钟响的时候再唤醒,这也需要借助外部中断。

还有USB唤醒、以太网唤醒也都是类似的作用。当然我们本节主要学习引脚外部中断,这是四个“蹭网”的,知道一下就行了。

6、 触发响应方式:中断响应/事件响应

最后外部中断的触发响应方式可以是中断响应和事件响应。

中断响应好理解,就是申请中断,让CPU执行中断函数。

那事件响应是什么意思呢?这个其实是STM32对外部中断增加的一种额外的功能,当外部中断检测到引脚电平变化时,正常的流程是选择触发中断。但在STM32中也可以选择触发一个事件。如果选择触发事件,那外部中断的信号就不会通向CPU了,而是通向其他的外设,用来触发其他外设的操作。比如触发ADC转换,触发DMA等。

所以总结一下就是中断响应是正常的流程。引脚电平触发。中断事件响应不会触发中断,而是触发别的外设操作,属于外设之间的联合工作。

EXTI基本结构

接下来我们就来看一下外部中断的基本结构,这个图就是外部中断的整体结构图。

图:EXTI基本结构图

P11-EXTI外部中断-13.png

首先最左边是GPIO口的外设的,比如GPIOA、GPIOB、GPIOC等等。每个GPIO外设有16个引脚,所以进来16根线。

我们刚才这里说了EXTI模块只有16个GPIO的通道,但这里每个GPL外设都有16个引脚。如果每个引脚占用一个通道,那EXTI的16个通道显然就不够用了。

所以在这里会有一个AFIO中断引脚选择的电路模块。

这个AFIO就是一个数据选择器,它可以在这前面3个GPIO外设的16个引脚,选择其中一个连接到后面的EXTI的通道里。

所以这前面说相同的Pin不能同时触发中断。因为对于PA0、PB0、PC0这些通过AFIO选择之后,只有其中一个能接到EXEI的通道0上。同理PA1、PB1、PC1这些也只能有一个接到通道1上,这就是所有GPIO口都能触发中断,但相同的Pin不能同时触发中断的原因。

然后通过AFIO选择之后的16个通道,就接到了EXTI边沿检测及控制电路上。同时下面这4个蹭网的外设也是并列接进来的。

这些加起来就组成了EXTI的20个输入信号。

然后经过EXTI电路之后,分为了两种输出。其中上面的这些接到了NVIC就是用来触发中断的。

这里注意一下,本来20路输出应该有20路中断的输出,但是可能ST公司觉得这20个输出太多了,比较占用NVIC的通道资源。所以就把其中外部中断的9到5和15到10给分配到了一个通道里。也就是说外部中断的9到5会触发同一个中断函数,15到10也会触发同一个中断函数。

在编程的时候,我们在这两个中断函数里需要再根据标志位来区分到底是哪个中断进来的。这个注意一下。

然后下面这里有20条输出线路到了其他外设,这就是用来触发其他外设操作的,也就是我们刚才说的事件响应。看完这个图,相信你对中断的整体流程就应该熟悉一些了。

P11-EXTI外部中断-12.png

AFIO复用IO口

然后我们再具体的看一下这里AFIO和EXTI的内部电路。那先看一下AFIO复用IO口。

- 1、AFIO主要用于引脚复用功能的选择和重定义

- 2、在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

图:AFIO选择中断引脚的结构图

P11-EXTI外部中断-14.png

这个结构图看上去就比较简单了,这里就是一系列的数据选择器。第一个输入是PA0、PB0、PC0等等,一直到PG0,尾号都是0。然后通过数据选择器最终选择一个接到EXTI0上,上面写的是配置这个寄存器的这些位,可以决定选择哪一个输入。

然后下面的EXTI1等等,一直到EXTI15都是数据选择器,这个好理解吧。

接着我们看一下左边的文字。

1、 AFIO主要用于引脚复用功能的选择和重定义

第一条是AFIO主要用于引脚复用功能的选择和重定义,也就是数据选择器的作用。

2、 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

然后第二条,在STM32中,AFIO主要完成两个任务,复用功能引脚重映射,中断引脚选择。其中复用功能引脚重映射就是这里,就是我们最开始提到的这个引脚定义表。当我们想把这些默认复用功能的引角换到重定义的这个位置来,就是用AFIO来完成。这也是AFIO的一大主要功能。

图:引脚定义表

P11-EXTI外部中断-15.png

那另外一个功能就是我们刚才提到的中段引脚选择了,这个也是用AFIO来完成的。

EXTI的内部框图

下面就是EXTI的内部框图了。

图:EXTI的内部框图

P11-EXTI外部中断-16.png

这里可以看到EXTI的右边就是20根输入线。然后输入线首先进入边沿检测电路,在上面的上升沿寄存器和下降沿寄存器可以选择是上身沿触发还是下降沿触发,或者两个都触发。接着触发信号就进入到这个或门的输入端了。

或门

简单介绍一下,这种弯弯的符号是或门,它可以有多个输入,但只能有一个输出,执行的是或的逻辑。在输入端只要有一个是高电平1,输出就是高电平1,只有全部输入低电平0,输出才为0。

与门

然后还有这种带点直边的符号是与门。它同样也可以有多个输入,但只能有一个输出,执行的是与的逻辑。在输入端只要有一个是低电平0,输出就是0,只有全部输入1,输出才为1。

非门

另外还有一种三角号加个圈的是非门,它只有一个输入一个输出,输入1就输出0,输入0就输出1,执行的是非的逻辑。

数据选择器

最后还有一种就是刚才这里说的数据选择器,它的符号是一个梯形,有多个输入一个输出,在侧面有选择控制端,根据控制端的数据从输入选择一个接到输出。

这些就是常见的逻辑符号,了解一下,在STM32的模块框图里还是非常常见的。

……省略对EXTI的内部框图的讲解

到这里有关中断系统、NVIC中断控制器和EXTI外部中断的内容我们就讲完了。

使用外部中断模块的特性

最后看一下本节课配合外部中断我们所使用的硬件模块。对于外部中断来说,我们刚学习完它的原理和结构,那到底什么样的设备需要用到外部终端呢?使用外部中断有什么好处呢?

在这里我大概总结了使用外部中断模块的特性。

就是对于STM32来说,想要获取的信号是外部驱动的很快的突发信号。

旋转编码器

比如旋转编码器的输出信号,我可能很久都不会拧它,这时不需要STM32做任何事,但是我一拧它就会有很多脉冲波形,需要STM32接收。这个信号是突发的,STM32不知道什么时候来。同时它是外部驱动的,STM32只能被动读取,最后这个信号非常快,STM32稍微晚来一点读取,就会错过很多波形。所以对于这种情况来说,就可以考虑使用STM32的外部中断了。有脉冲过来,STM32立即进入中断函数处理,没有脉冲的时候,STM32就专心做其他事情。

红外遥控接收头

另外还有,比如红外遥控接收头的输出,接收到遥控数据之后,它会输出一段波形,这个波形转瞬即逝并且不会等你,所以就需要我们用外部中断来读取。

按键

最后还有一个按键,虽然它的动作也是外部驱动的突发事件,但我并不推荐使用外部中断来读取按键,因为外部中断不好处理按键抖动和松手检测的问题。对于按键来说,它的输出波形也不是转瞬即逝的,所以要求不高的话可以在主程序中循环读取。如果不想用主循环读取的话,可以考虑一下定时器中断读取的方式,这样既可以做到后台读取按键值不阻塞主程序,也可以很好的处理按键抖动和松手检测的问题。这个感兴趣的话可以了解一下。

了解完外部中断的适用场景之后,我们就来看一下这个编码器介绍。

旋转编码器

概念

1、旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向

2、类型:机械触点式/霍尔传感器式/光栅式

旋转编码器-详解

首先旋转编码器它是用来测量位置、速度或旋转方向的装置。当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向。

下面是旋转编码器的类型,有机械触点式、霍尔传感器式、光栅式等类型。

最简单的旋转编码器

那旋转编码器其实是怎么工作的呢?首先看一下下面的第一个图。

图:最简单的旋转编码器

P11-EXTI外部中断-17.png

它是一种最简单的编码器样式的。这里使用的也是对射式红外传感器来测速的。为了测速还需要配合一个这样的光栅编码盘。当这个编码盘转动时,红外传感器的红外光就会出现遮挡、透过、遮挡、透过这样的现象,对应模块输出的电平就是高低电平交替的方波。这个方波的个数代表了转过的角度,方波的频率代表转速。

那我们就可以用外部中断来捕获这个方波的边沿,以此判断位置和速度。不过这个模块只有一路输出,正转反转输出波形没法区分,所以这种测速方法只能测位置和速度,不能测量旋转方向。为了进一步测量方向,我们就可以用后面的几种编码器。

我们采用的旋转编码器

第二个图片就是我们套件里的旋转编码器。

图:我们采用的旋转编码器

P11-EXTI外部中断-18.png

左边是它的外观,右边是它的内部拆解结构。可以看到它内部是用金属触点来进行通断的,所以它是一种机械触点式编码器。这里左右是两部分开关触点,其中内侧的这两根细的触点,都是和中间的这个引角连接的。外侧的触点,左边的接在这个引脚,右边的接在这个引脚,这就是这些触点的连接方式。然后中间这个圆的金属片是一个按键,我们这个旋转编码器的轴是可以按下去的。这个按键的两根线就在上面引出来了。按键的轴按下,上面两根线短路,松手,上面两根线断开,就是个普通按键。

然后再看一下编码盘,它也是一系列像光栅一样的东西,只不过这是金属触点,在旋转时,依次接通和断开两边的触点。并且还有一个关键的部分是这个金属盘的位置是经过设计的,它能让两侧触点的通断产生一个90度的相位差,最终配合一下外部电路,这个编码器的两个输出就会输出这样的波形。当正转时,左边的银角就是A相引脚,输出一个方波信号,同时右侧的引脚就是B项引脚,输出一个和它相位相差90度的波形。

比如正向旋转时,B相输出是滞后90度的,就是这样的。反向旋转时A相还是方波信号。那B相就会提前90度。

图:第一种情况。正向旋转时,B相输出是滞后90度。第二种情况。反向旋转时,B相输出是提前90度。

P11-EXTI外部中断-19.png

这样正转和反转就可以区分开了,这种相位相差90度的波形就叫正交波形。带正交波形信号输出的编码器是可以用来测方向的,这就是单相输出和两相正交输出的区别。当然还有的编码器不是输出正交波形,而是一个引脚输出方波信号代表转速,另一个输出高低电平代表旋转方向。这种不是正交数字的编码器,但也是可以测量方向的。

第三个图,这种是直接附在电机后面的编码器,这种是霍尔传感器形式的。编码器中间是一个圆形磁铁,边上有两个位置错开的霍尔传感器。当磁铁旋转时,通过霍尔传感器就可以输出正交的风波信号。

最后一个就是独立的编码器原件,它的输入轴转动时输出就会有波形,这个也是可以测速和测方向的,具体用法再看相应的手册。当然第二个图里的这个编码器一般是用来进行调解的,比如音响调节音量这样的用途。因为它是触点接触的形式,所以不适合电机这种高速旋转的地方。另外几种都是非接触的形式,可以用于电机测速。电机测速在电机驱动的应用中还是非常常见的。

我们本节就用这种旋转编码器模块来学习一下。当然我们本节先学习一下外部中断读取编码器计次数据的用法。以后我们学了定时器,还会再来看一下编码器测速的用途了。

旋转编码器的硬件电路

旋转编码器的硬件电路-分析

接下来我们看一下这个旋转编码器的硬件电路。

图:旋转编码器的硬件电路

P11-EXTI外部中断-20.png

这里左边这个是模块的电路图,这个图里中间这个就是旋转编码器上面按键的两根线,这个模块并没有使用,是悬空的。下面的这里就是编码器内部的两个触点,旋转轴旋转时,这两个触点以相位相差90度的方式交替导通。因为这只是个开关信号,所以要配合外围电路才能输出高低电平。

看一下左边,这里接了一个10k的上拉电阻,默认没旋转的情况下,这个点被上拉为高电平。通过R3这个电阻输出到A端口的就也是高电平。当旋转时内部这里触点导通,那这个点就直接被拉低到GND了,再通过R3输出A端口就是低电平了。

之后,这个R3是一个输出限流电阻,它是为了防止模块引脚电流过大的。这个C1是输出滤波电容,可以防止一些输出信号抖动。这个滤波电容见了很多是吧?

然后右边的这一部分电路和左边的也是一模一样的,它的输出接到了B端口上。最后中间这里可以看到这个模块的C端口就直接接到了GND,那这些就是这个模块的电路图。

旋转编码器接线

图:旋转编码器接线

P11-EXTI外部中断-21.png

然后右边我们在使用这个模块的时候,接线就很简单了,上面的VCC,GND接电源,下面的A相输出和B相输出接到STM32的两个引脚上。比如PB0和PB1,注意引脚的GPIO_Pin编号不要一样就行了。然后中间的C引脚就是GND,我们暂时不用。

看手册

最后我们再来看一下手册,大概的看一下每个外设在手册里的介绍。

首先是NVIC,因为NVIC是内核外设,所以要在这个Coretex-M3编程手册(《STM32F10xxx Coretex-M3编程手册.pdf》)里找。这个Coretex-M3编程手册里就是内核和内核外设的详细介绍。

如果你想研究一下内核的运转细节,可以看一下这个手册。不过这个手册我目前还没找到中文的版本。我们可以在目录里找到内核外设NVIC这一节,这里就有NVIC的一些说明,大家感兴趣的话可以自己用翻译软件看一下。

图:Coretex-M3编程手册 中的 NVIC部分截图

P11-EXTI外部中断-22.png

然后是NVIC的一些寄存器,包括中断设置使能寄存器、中断清除使能寄存器、中断设置挂起寄存器、中断清除挂起寄存器、中断活动位寄存器、中断优先级寄存器。

这个中断优先级寄存器就是用来设置每个中断的优先级的。这个如果直接配置寄存器设置优先级的话,那还是比较复杂的。不过我们用库函数的话,那就简单了,直接给结构体赋值就行了。所以这个寄存器就大致看一下就行了。不过你要知道我们的库函数最终还是要落实到这个寄存器上来的。

接着下面还有一个软件触发中断寄存器,然后这后面还有一些中断执行细节的描述,感兴趣的可以自己看一下。这些就是手册里对NVIC的介绍了。另外这些NVIC寄存器里还少了一个东西,就是中断分组的配置。

中断分组的配置寄存器是被分配到了这个SCB里面的,在这个SCB_AIRCR里,这三位就是用来配置中断分组的。

然后下面有中断分组的描述,和我PPT里也是一样,大家可以看一下。好,NVIC的手册,我就带大家要看到这里。

图:中断分组的配置寄存器

P11-EXTI外部中断-23.png

然后我们再打开这个STM32的参考手册,带大家快速过一下手册的内容。我们可以在目录里找到中断和事件这一节,这里就是中断系统和外部中断的介绍。首先是NVIC的概述,然后是中断向量表。

接着就是外部中断EXTI的介绍了。然后是框图,这个我也给大家讲过,这里还有外部中断唤醒事件的说明。最后是外部中断的功能说明。然后是中断的线路映象,也就是中断引脚的选择。

这一部分实际上是在AFIO里的,那最后就是外部中断的寄存器描述了,这里有中断屏蔽寄存器、事件屏蔽计算器、上升沿触发选择寄存器、下降沿触发选择寄存器、软件触发计算器、挂起寄存器。这些寄存器看上去应该不难理解吧。在这个中断的框图里也都有体现。

最后来看一下AFIO,在这个目录里找到GPIO和AFIO,打开AFIO这一节,这里对AFIO的描述就只有这一句话,就是复用功能引脚重映射的意思。然后下面这些全部都是重映射的表,通过配置寄存器就可以在这些映射关系表里切换了。最后就是寄存器描述了,怎么切换配置这些寄存器就行了。当然我们使用库函数那就更加方便了,调用一个函数填两个参数就行了。最后几个卷起我们就可以看到,这些就是用来选择外部中断引脚的。好,那本小节中断系统和外部中断的理论部分我们就学到这里。下一小节我们再来学习一下外部中断的代码部分。

P11-EXTI外部中断-2.jpg

END

END:本节内容到此结束。

个人提升之余,别忘了和小伙伴积极交流,很多人觉得他们在思考,而实际上他们只是在重新整理自己的偏见。请珍惜和他人交流讨论的机会。


END1.jpg

希望你每一天都有所收获,进步up up up。今天的我们并不比昨天更聪明,但一定要比昨天更睿智。


END2.jpg