(八)零基础开发小安派-Eyes-S1【外设篇】——GPIO中断编程

[复制链接]
查看3651 | 回复20 | 2023-9-15 17:02:28 | 显示全部楼层 |阅读模式

本帖最后由 Ai-Thinker小泽 于 2023-9-15 17:04 编辑

本帖最后由 Ai-Thinker小泽 于 2023-9-15 17:03 编辑

零基础开发小安派-Eyes-S1【外设篇】——GPIO中断编程

上期的GPIO输入输出编程是基于在main函数中设置while循环不断的改变IO0的电平,同时打印IO1的电平状态。本期了解关于中断编程的概念方法。

一、中断概念了解

我们在常规的程序中,都是在main函数中设置While函数不断运行代码。 而中断的概念则是打断当前的程序,并保护现场,执行另外的程序,而后回到最初打断的位置,举个恰当的例子,比如我们在敲代码,忽然外卖小哥敲门说外卖到了,于是我们先ctrl+s保存,然后去拿完外卖顺便吃了回来继续敲代码。敲代码就是我们的常规程序(发量危),中断源就是外卖小哥的敲门声,而拿外卖吃外卖的过程就是中断服务函数。这就是中断的基本概念。

image.png

为什么要使用中断?中断是为了应对各种突发事件,如敲代码的时候忽然有人敲门送外卖。正如使用按键扫描检测和外部中断的区别来说,按键扫描会一直在循环中持续扫描按键在状态,正如我们在敲代码时,因为不知道外卖什么时候送来,还要时不时看看有没有人敲门,注意力都用在盯着门上了,怎么能认真敲代码。而中断正如我们已经设置好了耳朵,我们可以认真敲代码,当有人敲门时我们再自然而然的去开门即可,不需要一直盯着门看。

1.中断源

在上面的例子中,中断源就是外卖小哥的敲门声。我们在开门之后他就会停止敲门,但是实际上我们还是需要手动的告诉MCU不用敲门了,这也就是要清除中断源 的操作。

2.中断服务函数

中断服务函数,也就是我们触发中断后需要执行的操作,这里的吃外卖过程就是中断服务函数的执行过程。一般会在中断服务函数内清除中断源,也就是让外卖小哥别敲门了。

二、中断的配置函数

1.bflb_gpio_int_init

说明: gpio 外部中断初始化

void bflb_gpio_int_init(struct bflb_device_s *dev, uint8_t pin, uint8_t trig_mode);
parameter description
dev 设备句柄
pin gpio pin
trig_mode 中断触发模式

2.bflb_gpio_int_mask

说明:gpio 外部中断屏蔽开关

void bflb_gpio_int_mask(struct bflb_device_s *dev, uint8_t pin, bool mask);
parameter description
dev 设备句柄
pin gpio pin
mask 是否屏蔽中断

3.bflb_gpio_get_intstatus

说明: 获取 gpio 外部中断是否触发的标志

bool bflb_gpio_get_intstatus(struct bflb_device_s *dev, uint8_t pin);
parameter description
dev 设备句柄
pin gpio pin
return true为触发,false未触发

4.bflb_gpio_int_clear

说明: 清除 gpio 中断标志

void bflb_gpio_int_clear(struct bflb_device_s *dev, uint8_t pin);
parameter description
dev 设备句柄
pin gpio pin

5.bflb_irq_attach

说明:设置触发中断后进入的回调函数

int bflb_irq_attach(int irq, irq_callback isr, void *arg)
parameter description
irq 中断号
isr 中断服务函数
arg 设备句柄

6.bflb_irq_enable

说明:中断使能

void bflb_irq_enable(int irq)
parameter description
irq 中断号

其他:bflb_gpio_uart_init

说明: gpio 配置成 uart 的某一个功能,可配置的可能参考上一期的gpio uart function

void bflb_gpio_uart_init(struct bflb_device_s *dev, uint8_t pin, uint8_t uart_func);
parameter description
dev 设备句柄
pin gpio pin
uart_func uart具体某一功能

三、示例讲解

这里还是对SDK的中断示例稍作修改

main

#include "bflb_gpio.h"   
#include "bflb_mtimer.h"
#include "board.h"

struct bflb_device_s *gpio;       //设置控制的外设句柄,取名gpio

void gpio_isr(int irq, void *arg)    //中断服务函数
{
    bool intstatus = bflb_gpio_get_intstatus(gpio, GPIO_PIN_0);//检测中断是否发生
    if (intstatus) {            //前面的instatus是bool类型,为true,也就是中断发生
        bflb_gpio_int_clear(gpio, GPIO_PIN_0);//清除中断源,也就是例子里的敲门声
        printf("Finished eating\r\n");//输出信息,“吃完了”
    }
}

int main(void)
{
    board_init();

    gpio = bflb_device_get_by_name("gpio");   //给外设句柄复位gpio句柄
    printf("gpio interrupt\r\n");

    bflb_gpio_int_init(gpio, GPIO_PIN_0, GPIO_INT_TRIG_MODE_SYNC_LOW_LEVEL);//第三个参数设置为低电平触发
    bflb_gpio_int_mask(gpio, GPIO_PIN_0, false);//是否屏蔽中断,设置为false

    bflb_irq_attach(gpio->irq_num, gpio_isr, gpio);//第二个参数为中断服务函数的函数名
    bflb_irq_enable(gpio->irq_num);//中断使能

    while (1) {
        printf("I am typing the code\r\n");//在常规的while程序中输出“我在敲代码”
        bflb_mtimer_delay_ms(2000); 
    }
}

效果

当正常识别串口信息时,只会每两秒打印一次“I am typing the code” 当我用IO0去碰一下TTL的GND脚,也就是拉低,触发了中断,每进入一次中断会打印一次“Finished eatingimage.png

这里打印了许多次,说明我触发了多次中断,毕竟只是使用杜邦线碰一下地,程序的运行和检测是十分快的,所以及时碰一下还是触发了许多次中断,实际上使用按键会更加灵敏,需要注意的是,不要在中断中使用delay延迟函数!中断是为了应对突发状况,处理的越快越好,而延迟会让整个系统暂停在中断里等待,相当于堵塞在这里,直到延迟结束。

本帖被以下淘专辑推荐:

回复

使用道具 举报

496199544 | 2023-9-15 17:13:46 | 显示全部楼层
学习
回复

使用道具 举报

ifwz1729 | 2023-9-15 17:21:35 | 显示全部楼层
泽哥yyds!
知足常乐
回复

使用道具 举报

WangChong | 2023-9-15 19:02:23 | 显示全部楼层
中断优先级没有吗?还有嵌套中断?
回复 支持 反对

使用道具 举报

WYG | 2023-9-15 20:04:05 | 显示全部楼层
打卡
回复

使用道具 举报

爱笑 | 2023-9-15 20:49:01 来自手机 | 显示全部楼层
打卡!
用心做好保姆工作
回复

使用道具 举报

18350766600@139 | 2023-9-15 23:24:14 | 显示全部楼层
很详细,打卡打卡
回复 支持 反对

使用道具 举报

可乐klelee | 2023-9-16 11:53:06 来自手机 | 显示全部楼层
打卡学习
回复

使用道具 举报

lsrly | 2023-9-29 18:33:22 | 显示全部楼层
根着大神学
好好学习,努力挣钱,专心
回复 支持 反对

使用道具 举报

干簧管 | 2023-11-16 10:36:26 | 显示全部楼层
跟着大神学
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则