瑞萨单片机开发教程[五] ICU外部中断实验

📅 2026/7/26 22:37:00
瑞萨单片机开发教程[五] ICU外部中断实验
开发板官网https://www.edevkit.com/瑞萨单片机开发教程瑞萨单片机开发教程[一] e2-studio DAP LINK开发环境搭建瑞萨单片机开发教程[二] Keil/RASC开发环境搭建​瑞萨单片机开发教程[三] GPIO输出–点亮led实验瑞萨单片机开发教程[四] GPIO输入–按键key实验本章目标熟悉RASC配置ICU外部中断的操作使用掌握GPIO的ICU 配置 API的使用掌握ICU触发回调的使用1 硬件设计2 软件设计2.2 新建工程外部中断GPIO检测需要用到led复制一份“04 GPIO-led”修改文件夹名“06 ICU_External_IRQ”双击打开“EBF_RA6M5.uvprojx”工程通过keil的新建文件新建“key_irq.c”和“key_irq.h”保存到目录下的\src文件夹下。将代码文件放到 “src” 文件夹下之后 Keil 软件并不会自动将它们加入到工程这时候需要打开 RASC FSP 配置界面 点击一次中间的 “Generate Project Content” 按钮自动生成文件架构。从而 “src” 文件夹下的代码文件就会被自动加入进工程中。接着关闭 FSP 配置界面返回到 Keil进行一次编译后会弹出一个提示框提示工程结构发生了变化点击“是”即可。最后key_irq.c和key_irq.h加入到工程中。2.2 FSP配置外部中断连接的引脚IO是P105, 需要配置ICU外设模块把引脚与ICU中断通道IPQ00连接起来使能中断后检测到IO引脚边沿电平时会触发中断。查看RA6M5数据手册的引脚中断表看到P105对应IRQ0。keil界面选择“Tools”-“RA Smart configuarater”打开RASC界面。在 FSP 配置界面里面点开 “Pins”- “Peripherals”- “Input”- “ICU0” 在“input/output”选择IRQ00通道。①选择“Pins”包含所有IO和外围设备。②选择“Peripherals”外围设备。③选择ICU的ICU0。④“operation Mode”选择“Enable”使能ICU。⑤选择IRQ00通道配置选择P105引脚。引脚通道配置完还需要添加外部中断r_icu的Stack模块。①选择“Stack”。②选择“New Stack”,添加外设模块。③选择“Input”模块。④选择“Input”模块的r_icu功能新建一个模块。①新建了一个“g_external_irq0”模块。②点击这个模块显示“Properties”属性界面。③属性配置列表按上图进行配置特别注意“callback”需要填写回调的函数名需要用户定义。External IRQ 属性描述Name名称Channel通道IRQ中断号Trigger触发方式上升沿、下降沿、双边沿或低电平触发Digital Filtering数字滤波使能Digital Filtering Sample Clock (Only valid when Digital Filtering is Enabled)数字滤波采样时钟Callback中断回调函数用户定义函数名Pin Interrupt Priority中断优先级配置完成之后可以按下快捷键“Ctrl S”保存 最后点击 “Generate Project Content” 按钮让软件自动生成配置代码即可。引脚配置信息引脚配置还是在pin_data.c文件里生成。constioport_pin_cfg_tg_bsp_pin_cfg_data[]{{.pinBSP_IO_PORT_01_PIN_05,.pin_cfg((uint32_t)IOPORT_CFG_IRQ_ENABLE|(uint32_t)IOPORT_CFG_PORT_DIRECTION_INPUT)},}ICU配置信息ICU模块信息会在common_data.c文件里生成。在RASC里配置的IRQ通道、触发方式和中断服务函数等都会在common_data.c生成一个external_irq_cfg_t结构体里面的内容跟配置时选择的参数一致。#includecommon_data.hicu_instance_ctrl_tg_external_irq0_ctrl;/** External IRQ extended configuration for ICU HAL driver */consticu_extended_cfg_tg_external_irq0_ext_cfg{.filter_srcEXTERNAL_IRQ_DIGITAL_FILTER_PCLK_DIV,};constexternal_irq_cfg_tg_external_irq0_cfg{.channel0,.triggerEXTERNAL_IRQ_TRIG_RISING,.filter_enablefalse,.clock_source_divEXTERNAL_IRQ_CLOCK_SOURCE_DIV_64,.p_callbackkey_external_irq_callback,/** If NULL then do not add */#ifdefined(NULL).p_contextNULL,#else.p_contextNULL,#endif.p_extend(void*)g_external_irq0_ext_cfg,.ipl(12),#ifdefined(VECTOR_NUMBER_ICU_IRQ0).irqVECTOR_NUMBER_ICU_IRQ0,#else.irqFSP_INVALID_VECTOR,#endif};/* Instance structure to use this module. */constexternal_irq_instance_tg_external_irq0{.p_ctrlg_external_irq0_ctrl,.p_cfgg_external_irq0_cfg,.p_apig_external_irq_on_icu};中断回调定义中断回调函数的原型已经在common_data.h中进行了声明需要用户在自己的程序中实现它。voidkey_external_irq_callback(external_irq_callback_args_t*p_args);其参数类型是external_irq_callback_args_t结构体指针这个结构体的原型如下typedefstructst_external_irq_callback_args{/** Placeholder for user data. Set in ref external_irq_api_t::open function in ref external_irq_cfg_t. */voidconst*p_context;uint32_tchannel;/// The physical hardware channel that caused the interrupt.}external_irq_callback_args_t;这个结构体仅表明外部中断的内容context和通道channel而context在初始化时被设置为NULL没有使用。因而能使用的只有通道值用来判定发生了哪个通道的中断。2.3 程序设计程序的入口函数 main 函数调用了 hal_entry 函数。 打开 “hal_entry.c” 文件在 hal_entry 函数里面编写代码。实现按键引脚的外部中断检测配置上升沿触发中断相当于按键按下松开才会产生上升沿触发中断调用中断回调函数判断是否是通道0把中断标识值1循环中判断中断标识中断一次就把LED灯翻转一次。打开引脚的ICU模块fsp_err_tR_ICU_ExternalIrqOpen(external_irq_ctrl_t*constp_api_ctrl,external_irq_cfg_tconst*constp_cfg)外部中断open函数用于配置外部中断的类型、设置回调函数、设置通道等第一个参数是external_irq_ctrl_t类型的第二个参数是external_irq_cfg_t的这个结构体描述了外部中断的通道、优先级、终端类型、触发方式等。使能外部中断fsp_err_tR_ICU_ExternalIrqEnable(external_irq_ctrl_t*constp_api_ctrl)使能和禁止外部中断的函数只需要传入一个外部中断接口控制结构体external_irq_ctrl_t类型的参数在“bsp_io.h”中定义了bsp_io_level_t电平状态值。在key_irq.h头文件里定义中断初始化函数。#ifndef__BSP_KEY_EXTERNAL_IRQ_H#define__BSP_KEY_EXTERNAL_IRQ_H#includehal_data.h// KEY 外部中断初始化函数voidkey_IRQ_Init(void);#endif在key_irq.c里实现初始化函数和中断回调函数。#includekey_irq.h// KEY 外部中断初始化函数voidkey_IRQ_Init(void){fsp_err_terrFSP_SUCCESS;// 打开ICU 模式errR_ICU_ExternalIrqOpen(g_external_irq0_ctrl,g_external_irq0_cfg);// 允许中断errR_ICU_ExternalIrqEnable(g_external_irq0_ctrl);}volatilebool key1_pressfalse;//按键中断回调函数voidkey_external_irq_callback(external_irq_callback_args_t*p_args){// 判断中断通道if(p_args-channel0){key1_presstrue;// 按键KEY1按下}}在 “hal_entry.c” 文件中添加头文件 “key_irq.h” 在hal_entry 入口函数初始化key_irq在循环中扫描按键标识检测到按下就标识置0并翻转led灯状态。externvolatilebool key1_press;voidhal_entry(void){/* TODO: add your own code here */led_Init();// LED 初始化key_IRQ_Init();// KEY 外部中断初始化while(1){//判断按键 KEY1_SW2 是否被按下if(key1_press){key1_pressfalse;//标志位清零LED1_TOGGLE;//LED1 翻转}R_BSP_SoftwareDelay(1,BSP_DELAY_UNITS_SECONDS);//延时1秒}#ifBSP_TZ_SECURE_BUILD/* Enter non-secure code */R_BSP_NonSecureEnter();#endif}3 下载验证连接下载器将程序编译并下载到开发板之后按下复位按键来复位开发板可以观察到按下松开按键led灯亮再次按键led灯灭重复操作LED灯状态翻转切换。