【瑞萨RA_FSP】外部中断


一、外部引脚中断

1. ICU框图

在这里插入图片描述
根据ICU的功能框图可以知道,首先需要配置IRQCR寄存器(IRQ Control Register,IRQ英文全称:Interrupt ReQuest,中文名:中断请求)。之后配置IELSR寄存器(英文全称:ICU Event Link Setting Register,中文名:中断控制单元事件链接设置寄存器)。之后使能IR寄存器,最后配置NVIC。

2. 相应寄存器介绍
① IRQCR介绍
Interrupt Request Control Register(IRQCR) — 中断请求控制寄存器,这个寄存器拥有0-15个通道,有三个标志位: (1) IRQMD[1:0]检测感知选择 (2) FCLKSEL[1:0]数字滤波采样时钟选择 (3) FLTEN数字滤波器使能

IRQ控制寄存器:
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

二、中断过程

当中断来临的时候会最先经过IRQ寄存器,IRQ寄存器检测到中断的时候,会向中央处理嵌套向量中断控制器NVIC发送中断信号, 当NVIC检测到中断请求的时候,会将相应的中断服务函数进行挂起。之后将运行的八个寄存器进行压栈,压栈完成之后将中断服务程序进行激活。 之后将原先压栈的寄存器取出,继续运行之前的程序。

中断抢占的过程:
当中断来临的时候会最先经过IRQ寄存器,IRQ寄存器检测到中断的时候,会向中央处理嵌套向量中断控制器NVIC发送中断信号, 当NVIC检测到中断请求的时候,会将相应的中断服务函数进行挂起。之后将运行的八个寄存器进行压栈,堆栈完成之后将中断服务程序进行激活。 此时当另一个优先级更高的中断源发生请求的时候,会将相应的中断服务函数进行挂起。之后将当前运行的八个寄存器进行压栈,压栈完成之后将中断服务程序进行激活。 当中断服务程序运行完之后会将原先压栈的寄存器取出,之后继续运行之前中断服务的程序。中断服务程序运行完成之后之后将原先压栈的寄存器取出,继续运行之前的程序。

三、按键外部中断

中断在嵌入式应用中的地位不言而喻,几乎每个控制器都有中断功能。中断对事件得到第一时间处理是非常重要的。 我们设计使用按键来作为触发源,使得控制器产生中断,并在中断服务函数中实现控制LED灯的任务。

1. 硬件设计
轻触按键在按下时会使得按键的两个引脚接通,通过电路设计可以使得在按键按下时引脚产生电平变化。

野火启明6M5开发板的按键电路设计如下:
在这里插入图片描述
其中,RES 按键是开发板的芯片复位按键,用于复位MCU芯片。 另外两个按键为用户可自定义的按键,可用于实现用户所需的功能。

在按键的电路设计中,与按键相并联的电容属于硬件滤波电容,可以在一定程度上防止按键抖动带来的误触发。 其实,用户也可以使用瑞萨RA MCU的IO引脚内部自带的数字滤波功能,这样可以去掉该电容,从而减少电路板的硬件成本。

开发板按键引脚分配和中断号:

KEY_1SW2:P004(IRQ9-DS)
KEY_2SW3:P005(IRQ10-DS)

2. 软件设计
① FSP配置
首先打开 “16_ICU_External_IRQ” 项目的 FSP 配置界面,接下来在这个界面里配置芯片的引脚及其相应的功能。

首先配置引脚连接到 ICU 的中断通道。
在这里插入图片描述
然后,依次点击 “Stacks” -> “New Stack” -> “Input”-> “External IRQ” 来加入外部中断模块, 如下图所示。由于使用两个按键,需要两个外部中断,所以这里需要加入2个外部中断模块。
在这里插入图片描述
第一个外部中断模块设置的是按键1的外部中断配置,按如下图所示进行设置:
在这里插入图片描述
第二个外部中断模块设置的是按键2的外部中断配置,按如下图所示进行设置:
在这里插入图片描述

外部中断模块(r_icu)的属性介绍如下表所示
在这里插入图片描述

配置完成之后可以按下快捷键“Ctrl + S”保存, 最后点右上角的 “Generate Project Content” 按钮,让软件自动生成配置代码即可。

② 按键外部中断初始化函数

/* KEY 外部中断初始化函数 */
void Key_IRQ_Init(void)
{
    
    
   fsp_err_t err = FSP_SUCCESS;

   /* Open ICU module */
   err = R_ICU_ExternalIrqOpen(&g_external_irq9_ctrl, &g_external_irq9_cfg);
   err = R_ICU_ExternalIrqOpen(&g_external_irq10_ctrl, &g_external_irq10_cfg);
   /* 允许中断 */
   err = R_ICU_ExternalIrqEnable(&g_external_irq9_ctrl);
   err = R_ICU_ExternalIrqEnable(&g_external_irq10_ctrl);
}
  1. R_ICU_ExternalIrqOpen() 用于打开一个外部中断模块实例。

  2. R_ICU_ExternalIrqEnable() 用于使能外部中断,使能后即可触发产生外部中断。

③ 按键中断回调函数
因为之前的 FSP 配置里面 Callback 属性配置的都是同一个中断回调函数, 因此,我们仅需实现一个中断回调函数即可。当然,中断回调函数也可设置为不同的两个函数,由用户定义。

两个按键共用 key_external_irq_callback 中断回调函数, 并通过 p_args->channel 参数来判断是哪个中断通道产生了中断从而判断是哪个按键按下,该函数如下:

/* 按键按下标志 */
volatile bool key1_sw2_press = false;
volatile bool key2_sw3_press = false;

/* 按键中断回调函数 */
void key_external_irq_callback(external_irq_callback_args_t *p_args)
{
    
    
   /* 判断中断通道 */
   if (9 == p_args->channel)
   {
    
    
      key1_sw2_press = true;   // 按键KEY1_SW2按下
   }
   else if (10 == p_args->channel)
   {
    
    
      key2_sw3_press = true;   // 按键KEY2_SW3按下
   }
}

④ hal_entry入口函数

/* 用户头文件包含 */
#include "led/bsp_led.h"
#include "key/bsp_key_irq.h"


extern volatile bool key1_sw2_press;
extern volatile bool key2_sw3_press;


void hal_entry(void)
{
    
    
   /* TODO: add your own code here */

   LED_Init(); // LED 初始化
   Key_IRQ_Init(); // KEY 外部中断初始化

   while(1)
   {
    
    
      /* 判断按键 KEY1_SW2 是否被按下 */
      if (key1_sw2_press)
      {
    
    
            key1_sw2_press = false; //标志位清零

            LED2_TOGGLE;            //LED2 翻转
      }

      /* 判断按键 KEY2_SW3 是否被按下 */
      if (key2_sw3_press)
      {
    
    
            key2_sw3_press = false; //标志位清零

            LED3_TOGGLE;            //LED3 翻转
      }

      // LED1 闪烁指示程序正在运行
      LED1_TOGGLE;
      R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //延时1秒
      // 按键被按下触发中断后,在主循环中LED2或LED3最长会被推迟1秒翻转
   }


#if BSP_TZ_SECURE_BUILD
   /* Enter non-secure code */
   R_BSP_NonSecureEnter();
#endif
}

猜你喜欢

转载自blog.csdn.net/Dustinthewine/article/details/130754205