【裸机开发】IRQ 中断服务函数(三)—— 中断处理逻辑实现

本文详细介绍了如何使用C代码实现基于GPIO的中断服务函数,包括初始化全局中断、使能GPIO中断、设置中断触发方式以及注册中断服务函数。以按键中断为例,讲解了如何配置GPIO1_IO18为下降沿触发,并在按键按下时切换LED灯状态。最后给出了按键中断的初始化函数和中断服务函数的关键代码。
摘要由CSDN通过智能技术生成

实现了 IRQ 中断服务函数的汇编部分以后,接下来我们要使用C代码实现IRQ中断服务函数的具体逻辑,主要包含初始化和中断处理两部分。

  • 全局中断初始化(全局中断使能、IRQ中断使能)
  • 具体中断处理逻辑实现

我们这里的中断是由按键产生的,那我们要打开的就是按键引脚所关联的中断。


目录

一、外设引脚分析

二、外设中断初始化

1、基本流程

2、引脚使能(GPIO1_IMR)

3、设置触发方式(GPIO1_ICR2)

4、注册中断服务函数

三、总结


一、外设引脚分析

按键是对应的引脚是 UART1_CTS,我们需要将其复用为GPIO功能,我们找到 UART1 CTSB会发现,该引脚可以复用为 GPIO1_IO18

因此,要打开 GPIO1 的中断,就需要知道GPIO1 对应的中断ID。GPIO1_IO18 对应的中断ID就是67 + 32 = 99。注意还需要加上固有中断 SGI 和 PPI(一共32个)。

二、外设中断初始化

1、基本流程

外设中断初始化的整体流程如下,该过程中可能会用到如下寄存器:

  • GPIO1_ICR2  —— 配置中断的触发模式,也可以直接设置 GPIOx_EDGE_SEL 寄存器
  • GPIO1_IMR    —— 设置 GPIO1 某个引脚中断使能
  • GPIO_ISR       —— 中断状态寄存器,记录中断的发生状态(处理完中断以后,要对中断相应的bit位 置为1)

① GPIO1中断使能:这一步我们已经放到了《全局中断初始化》了。这里的 99 就包含了 GPIO1 的16~31引脚。

② 引脚中断使能:虽然使能了一批引脚的,但还需要指定某个引脚的中断使能

③ 设置中断触发方式:中断触发方式包含低电平触发、高电平触发、上升沿触发、下降沿触发等。

④ 注册中断服务函数:《全局中断初始化》只是暂时给每一种中断配置了一个临时的中断服务函数,这里我们要替换成真正的中断处理函数。

2、引脚使能(GPIO1_IMR)

设置引脚使能使用的是 GPIOx_IMR 寄存器。IMR寄存器占32bit,每一bit对应 GPIO1 的0 ~ 31引脚,我们要设置的是第 18 引脚,那就要将第 18 个 bit 置 1 。

GPIO1_IMR |= (1 << 18);

3、设置触发方式(GPIO1_ICR2)

方式一:GPIO1_ICR2

GPIO1_ICR2 控制的是16~31 引脚的触发方式。四种触发方式分别是:低电平、高电平、上升沿、下降沿

// 配置 GPIO1_IO18 中断触发方式(下降沿触发)
GPIO1_EDGE_SEL &= ~(1 << 18);
GPIO1_ICR2 |= (3 << 4);

注意:这里的 GPIO1_EDGE_SEL 寄存器是第二种设置触发中断的方法,一旦设置了会覆盖 GPIO1_ICR2 或者 GPIO1_ICR1 的对应位置的触发方式。所以事先将 GPIO1_EDGE_SEL 的第 18 bit 置 0 以防干扰 ICR 寄存器。

方式二:GPIO1_EDGE_SEL

GPIO1_EDGE_SEL只能用于设置边缘触发,无法设置低电平或者高电平触发。一旦设置会覆盖ICR寄存器对应位置的触发方式。

// 设置第 18 bit边缘触发
GPIO1_EDGE_SEL |= (1 << 18);

4、注册中断服务函数

现在我们要注册中断服务函数,也就是我们希望按键被按下时,执行何种操作。假设这里就设置成,当按键按下时,切换LED灯的状态。

// 注册中断服务函数
register_irqhandler(99, key_irqhandler);
unsigned int status = 1;

/* 按键中断服务函数 */
void key_irqhandler(void* userParams)
{
    switch_led(status);
    status = !status;
    GPIO1_ISR |= (1 << 18);    // 清除中断标志位
}

提示:有一点需要注意的是,中断服务函数执行完毕以后,要将 ISR 寄存器对应 bit 位置1(清除中断标志位),以表示该中断已经处理完毕。(也可以通过 ISR 寄存器判断中断是否发生

三、总结

unsigned int status = 1;

/* 按键中断服务函数 */
void key_irqhandler(void* userParams)
{
    switch_led(status);
    status = !status;
    GPIO1_ISR |= (1 << 18);    // 清除中断标志位
}

/* 按键中断初始化 */
void key_int_init()
{
    // GPIO1 中断使能
    GPIO1_IMR |= (1 << 18);

    // 配置 GPIO1_IO18 中断触发方式(下降沿触发)
    GPIO1_EDGE_SEL &= ~(1 << 18);
    GPIO1_ICR2 |= (3 << 4);

    // 注册中断服务函数
    register_irqhandler(99, key_irqhandler);
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值