【STC库函数】EXTI外部中断的使用

上一篇文章我们讲述了如何使用STC库函数来使用GPIO,今天我们来看看如何使用外部中断。

STC32G一共有49个中断源,其中有五个外部中断源,所以我们一次性最多可以使用5个外部中断。

而STC8G只有十一个中断源,外部中断源也是五个。

并且都是有四级中断优先级。

STC32G和STC8G的外部中断在结构上和库函数的使用上都差不多,所以接下来我主要以STC32G为例来讲解。

由于这个系列主要是讲如何使用库函数,所以我们就粗略地看看手册。

从上图可以看得出来,INT0和INT1的触发方式有两种,上升沿触发和下降沿触发。而INT234就只有一种下降沿触发。

中断优先级是有四级,从0 ~ 3,数值越大优先级越高,这和我们之前玩的STM32刚好反过来。

然后INT2和INT3的优先级只能是最低级的,如果我们拿STC去做项目的话,要注意这些点。

接着我们要做的就是把这五个外部中断的引脚给找出来。

STC32G12K128的是P32、P33、P36、P37、P30,都在P3下。

STC8G1K08A八个引脚的这个虽然只有八个引脚,但居然还全部都引出来了,也是把资源利用到极点了。

接下来看看库函数。

在此之前我们先聊聊NVIC,NVIC是嵌套向量中断控制器(Nested Vectored Interrupt Controller),也就是说我们有很多个中断源的时候,是有可能有冲突的,这时候就需要靠NVIC来处理中断嵌套。

然而STC里没有NVIC,NVIC是ARM里的。

那我为什么还要提一嘴NVIC呢?

因为STC的库函数里有NVIC这一部分,不过STC里的NVIC是中断系统而不是嵌套向量中断控制器,但是它们的功能是一样的,也就是说此NVIC非彼NVIC。

首先我们需要把STC32G_NVIC.c这个文件包含进我们的工程,不懂的小伙伴看看这个系列的第一篇搭建环境。

然后我们使用NVIC_INTn_Init来设置中断源的优先级,其中n是0 ~ 4,分别代表我们的五个外部中断源。

把NVIC这部分搞定后我们再看看EXTI的部分。

我们需要包含俩文件,一个是STC32G_Exti_Isr.c,另一个是STC32G_Exti.c。

里面初始化的函数就这一个,一个是外部中断号,另一个是结构体变量的指针,但是这个结构体只有一个成员,那就是中断触发的方式。

另外中断处理函数在STC32G_Exti.c里,但是我们没必要打开它修改中断处理函数。

因为它默认有个变量WakeUpSource,这个变量为1的时候就表示INT0触发了,变量为2的时候就表示INT1触发了……

所以我们只需要在main函数的主循环里反复判断这个变量的值即可知道有没有触发中断了,然后把真正的处理逻辑写在中断处理函数外面,这样可以避免中断处理函数长时间阻塞。

事实上官方提供的示例也是这么做的。

那接下来我给INT0接个按钮,让它中断的时候我就切换另一个GPIO的电平,然后给那个GPIO接个LED,这样就可以利用中断来实现通过按钮来控制LED的亮灭。

我们要做的就是把INT0的GPIO(P32)设为上拉输入,按钮的另一端接地,把连接LED的GPIO设为输出。

然后通过上面介绍的两个函数把NVIC和EXTI配置好就可以了……吗?

这边有个坑啊,我们光用库函数还不够,按照上面说的这样还不能完成我们理想中的功能。

我们回到手册。

要完成INT0的中断我们需要配置四个地方,分别是IT0,EX0,EA,PX0。

然后我们回到库函数看看。

可以看得出库函数只帮我们配置了三个地方,IT0,EX0,PX0,还剩下一个EA,需要我们自己去置1。

并且如果我们使用的是INT234这仨的话,是不需要Ext_Inilize这个函数的,只需要配置一下NVIC就行。

代码可以参考一下我下面这个。然后我在代码里没有对机械按键的按下进行处理,也就是说我们按下按钮一次可能会触发中断好多次,处理的方式就是在按下后延时个十毫秒左右再继续。

#include <STC32G.H>
#include "STC32G_GPIO.h"
#include "STC32G_Delay.h"
#include "STC32G_NVIC.h"
#include "STC32G_Exti.h"

void GPIO_Init(void){
    P3_MODE_IN_HIZ(GPIO_Pin_2);         // 高阻输入
    P3_PULL_UP_ENABLE(GPIO_Pin_2);      // 上拉电阻

    P2_MODE_OUT_PP(GPIO_Pin_7);
}

void EXTI_Init(void){
    EXTI_InitTypeDef initer;
    initer.EXTI_Mode = EXT_MODE_Fall;   // 下降沿触发
    Ext_Inilize(EXT_INT0, &initer);

    NVIC_INT0_Init(ENABLE, Priority_1); // 使能INT0,优先级1
}

void main(void){
    WTST = 0;		//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
	EAXSFR();		//扩展SFR(XFR)访问使能 
	CKCON = 0;      //提高访问XRAM速度
    
    EA = 1;         // 开启中断

    GPIO_Init();
    EXTI_Init();
    while(1){
        if(WakeUpSource == 1){      // INT0中断触发了
            WakeUpSource = 0;       // 清除标志
            P27 = !P27;
        }
    }
    return ;
}

上一篇:uniapp上传视频