最近项目上用到瑞萨单片机,把自己的学习过程记录一下,由于自己是第一次接触瑞萨单片机,一开始还是踩了不少坑。这里我用外部中断实现按键的长按用短按功能
一、实现原理
- 首先设置外中断触发方式为下降沿触发。(初始化已设置)
- 按键按下触发中断,此时记录时间,同时将触发方式改为上升沿触发。
- 按键释放,再次触发上升沿(此时触发方式为上升沿触发)。
- 主程序中判断按下的时间长短做相应的动作,此时将触发方式又重新改为下降沿触发。
二、具体实现
2.1 封装按键结构
typedef struct KEY_STRUCT
{
u8 key_status; /*按键状态*/
u8 key_press_time; /*按键按下时间*/
u8 key_lock; /*按键锁*/
u8 key_num; /*按键按下计数*/
};
2.2 瑞萨单片机外中断配置
根据前面的章节的介绍,这里主要是对外设IO引脚功能的映射,INTP2 对应的是 P122,如果选择上升沿触发最好把IO 加个下拉电阻拉低,如果选择下降沿触发最好把IO 加个上拉电阻拉搞,
在CS+中配置 外中断触发方式,然后点击生成代码即可
主要把INTP2 外部中断配置为下降沿触发
void R_INTC_Create(void)
{
PMK0 = 1U; /* disable INTP0 operation */
PIF0 = 0U; /* clear INTP0 interrupt flag */
PMK1 = 1U; /* disable INTP1 operation */
PIF1 = 0U; /* clear INTP1 interrupt flag */
PMK2 = 1U; /* disable INTP2 operation */
PIF2 = 0U; /* clear INTP2 interrupt flag */
PMK3 = 1U; /* disable INTP3 operation */
PIF3 = 0U; /* clear INTP3 interrupt flag */
/* Set INTP0 level 2 priority */
PPR10 = 1U;
PPR00 = 0U;
/* Set INTP2 level 2 priority */
PPR12 = 1U;
PPR02 = 0U;
EGN0 = _04_INTP2_EDGE_FALLING_SEL;
EGP0 = _01_INTP0_EDGE_RISING_SEL;
}
2.3 外部中断 & 定时器中断函数中 业务逻辑
- 按键按下 对key_struct.key_press_time 清零,按压状态置1,说明按键按下,这一步主要是对按压 初始时间清零,在定时器中对key_struct.key_press_time进行累加。
- 按键按下后 将触发方式改为上升沿触发。
- 按键释放后,中断又被触发,此时进入的是else 语句中,这里只把按键key_struct.key_status置0,这样在定时器中断就不会对key_struct.key_press_time中再进行累加了,这样一来我们只需要在主程序中判断按压时间的长短动作就可以了。
- 按键释放了,别忘了把触发方式又改回原来的下降沿触发。
外部中断中:
__interrupt static void r_intc2_interrupt(void)
{
if(key_struct.key_status==0) //按键按下 下降沿触发
{
key_struct.key_press_time=0;
key_struct.key_status=1;
key_struct.key_lock=0;
EGP0 |= _04_INTP2_EDGE_RISING_SEL; //上升沿触发 所有外中断都是这个寄存器,最好用 |
}
else //按键释放 上升沿触发
{
key_struct.key_status==0;
key_struct.key_lock=1;
EGN0 |= _04_INTP2_EDGE_FALLING_SEL; //下降沿触发
}
}
定时中断中 按压时间每1s 加一次
定时器中断中:
if(key_struct.key_status) //按键按压计时
{
key_struct.key_press_time++; //按键按压时间
}
2.4 例子
#define SHORT_PRESS 2 //两秒
#define LONG_PRESS 5 //5秒
void key_task(void)
{
if((key_struct.key_press_time<=SHORT_PRESS) && (key_struct.key_lock)) //小于2s 认为是短按
{
key_struct.key_press_time=0;
key_struct.key_lock=0;
key_struct.key_num +=1;
if(key_struct.key_num>=4)
{
key_struct.key_num=0;
}
}
else if((key_struct.key_press_time>=LONG_PRESS) && (key_struct.key_lock)) //大于5s 认为是长按
{
key_struct.key_num=4;
key_struct.key_press_time=0;
key_struct.key_lock=0;
}
}