外观
九、外部中断实验
中断基础知识
什么是中断
中断即打断,当单片机在顺序执行当前程序时,由于系统出现了某种需要紧急处理的情况,单片机暂停正在执行的程序,转而去执行紧急事务,当处理结束后单片机自动返回到原先暂停的程序中继续执行,这种执行过程由于外界的原因被打断的情况叫做中断。
外部中断
GD32E230外部中断EXTI(中断/事件控制器)包括21个相互独立的边沿检测电路并且能够向处理器内核产生中断请求或唤醒事件。 EXTI有三种触发类型:上升沿触发、下降沿触发和任意沿触发。EXTI中的每一个边沿检测电路都可以独立配置和屏蔽。
中断触发源
GD32E230外部中断EXTI触发源包括来自I/O管脚的16根线以及来自内部模块的5根线。通过配置SYSCFG_EXTISSx寄存器,所有的GPIO管脚都可以被选作EXTI的触发源。
中断优先级
GD32E230是M23内核,没有中断优先级分组的概念,支持四个优先级设置(0~3),数字越小,等级越高。
外部中断按键点灯
项目分析
本次项目需要通过板载EC11旋转编码器来点亮 熄灭LED灯。正转一格点亮LED灯,反转一格熄灭LED灯。根据前面的原理介绍,可以通过外部中断下降沿触发来判断正转还是反转。
配置流程
一般使用GPIO的外部中断功能,都需要有以下几个步骤:
- 开启时钟(包括GPIO时钟和系统配置时钟)
- 配置GPIO的模式
- 使能NVIC中断并配置优先级
- 配置GPIO中断
- 使能中断和清除中断标志位
- 编写中断服务函数
GD32单片机的任意引脚都可以配置为外部中断触发,我们对应的去使能引脚的外部中断功能即可。
开启时钟
GD32的所有外设资源时钟默认都是关闭的,在配置外设之前需要先开启对应的时钟。这里我们需要开启按键引脚的GPIO端口时钟,同时还需要开启系统配置时钟,用于中断。
C
//使能时钟GPIOB,CMP
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_CFGCMP);
1
2
3
2
3
配置GPIO模式
按键GPIO模式设置与前面的实验一致,将对应引脚设置为输入模式以及引脚上拉;
C
//设置引脚输入模式,上拉
gpio_mode_set(GPIOB,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_9);
1
2
2
使能NVIC中断并配置优先级
想要使用中断,必须先使能它,同时,考虑到有多个不同的中断可能同时呼叫CPU,中断具有优先级,当有两个或两个以上中断同时产生,会优先响应等级高的中断,若中断优先级相同,则会根据中断向量表的位置来进行响应,位置靠前的先进行响应。
中断使能函数有两个参数,第一个参数是中断源类型,第二个是优先级,相关函数说明文档在《GD32库函数使用说明》中可以找到;
这里EC11旋转编码器KEYA接入的引脚是PB4,对应外部中断是4,所以中断源选择EXTI4_15_IRQn,
注意这里并不需要对KEYA与KEYB引脚都进行中断使能,通过前面的原理分析,我们可以通过在KEYA的下降沿读取KEYB电平是否与KEYA一致来判断是正转还是反转。
C
//中断使能,优先级为1
nvic_irq_enable(EXTI4_15_IRQn,1U);
1
2
2
配置GPIO中断
使能中断源与中断优先级后,需要将中断线与GPIO引脚进行绑定,将对应GPIO引脚设置为中断引脚即可。
相关中断初始化函数在《GD32库函数使用说明指南》中有说明;
C
//配置中断线
syscfg_exti_line_config(EXTI_SOURCE_GPIOB,EXTI_SOURCE_PIN4);
1
2
2
现在该引脚已经可以作为中断引脚使用了,但是中断触发条件还未指明,需要对该中断线配置中断触发条件,当满足触发条件后,进入中断服务函数;
GD32E230总共有28条中断线,每一条中断线的对应的触发源在《GD32E230用户手册》第95页有说明;
相关中断初始化函数在《GD32库函数使用说明指南》中有说明;
C
//初始化中断线,设置为中断模式,下降沿触发
exti_init(EXTI_4,EXTI_INTERRUPT,EXTI_TRIG_FALLING);
1
2
2
使能中断和清除中断标志位
配置好中断后,就可以开启中断了;前面配置中断优先级的使能是开启终端总开关,这里是中断线的开关;
同时,为了确保中断能够有效进入,在使用前先清一下中断标志位.
C
//中断线使能
exti_interrupt_enable(EXTI_4);
1
2
2
C
//中断标志位清除
exti_interrupt_flag_clear(EXTI_4);
1
2
2
自此,中断配置完成,当指定中断线检测到下降沿到来时,进入中断服务函数。
编写中断服务函数
中断服务函数不同于普通函数,它的函数名是固定的,也就是函数入口地址固定,在startup_gd32e23x.s启动文件中有定义。
中断服务函数并不只为某一个特殊的中断事件服务,所以,在进入中断服务函数后,需要先进行判断,检测对应中断标志位是否有被置位,确定是指定中断事件产生后再进行相应的处理。处理完成后续将相应的中断标志位进行清除,以待下一次进入。
C
void EXTI4_15_IRQHandler(void)
{
if(RESET != exti_interrupt_flag_get(EXTI_4))
{
if(gpio_input_bit_get(GPIOB,GPIO_PIN_3) == RESET)
{
//反转
}
else
{
//正转
}
exti_interrupt_flag_clear(EXTI_4);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
资料下载
工程代码可前往gitee下载资料包,简易数字示波器资料包
注意事项
中断服务函数内不做耗时较长或死循环操作
中断服务函数是响应中断事件的处理,处理内容应简明扼要,如果需要延时或复杂逻辑,最好是通过全局变量标志位将其放置在顺序逻辑内执行。
多个中断事件如何处理
当程序中存在多个中断事件时,应对事件紧急程度进行排序,最紧急的分配最高优先级
EC11抖动问题如何解决
可以尝试在硬件引脚处加入100nf电容到GND进行硬件滤波;
件滤波原理是;通过判断两次EC11-A相位变化时;B相位是否发生变化;若发生变化,则根据变化判断正转或反转;若A相位上升沿、下降压B相位都没有发生变化;则是抖动;