瑞萨单片机开发教程[五] 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[]={{.pin=BSP_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结构体,里面的内容跟配置时选择的参数一致。
#include"common_data.h"icu_instance_ctrl_tg_external_irq0_ctrl;/** External IRQ extended configuration for ICU HAL driver */consticu_extended_cfg_tg_external_irq0_ext_cfg={.filter_src=EXTERNAL_IRQ_DIGITAL_FILTER_PCLK_DIV,};constexternal_irq_cfg_tg_external_irq0_cfg={.channel=0,.trigger=EXTERNAL_IRQ_TRIG_RISING,.filter_enable=false,.clock_source_div=EXTERNAL_IRQ_CLOCK_SOURCE_DIV_64,.p_callback=key_external_irq_callback,/** If NULL then do not add & */#ifdefined(NULL).p_context=NULL,#else.p_context=&NULL,#endif.p_extend=(void*)&g_external_irq0_ext_cfg,.ipl=(12),#ifdefined(VECTOR_NUMBER_ICU_IRQ0).irq=VECTOR_NUMBER_ICU_IRQ0,#else.irq=FSP_INVALID_VECTOR,#endif};/* Instance structure to use this module. */constexternal_irq_instance_tg_external_irq0={.p_ctrl=&g_external_irq0_ctrl,.p_cfg=&g_external_irq0_cfg,.p_api=&g_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#include"hal_data.h"// KEY 外部中断初始化函数voidkey_IRQ_Init(void);#endif在key_irq.c里实现初始化函数和中断回调函数。
#include"key_irq.h"// KEY 外部中断初始化函数voidkey_IRQ_Init(void){fsp_err_terr=FSP_SUCCESS;// 打开ICU 模式err=R_ICU_ExternalIrqOpen(&g_external_irq0_ctrl,&g_external_irq0_cfg);// 允许中断err=R_ICU_ExternalIrqEnable(&g_external_irq0_ctrl);}volatilebool key1_press=false;//按键中断回调函数voidkey_external_irq_callback(external_irq_callback_args_t*p_args){// 判断中断通道if(p_args->channel==0){key1_press=true;// 按键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_press=false;//标志位清零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灯状态翻转切换。