R5F1026A一款8位MCU
一、开发环境
使用瑞萨CS+ for CA,CX IDE开发新建工程,project->create new project...,选择MCU型号,设置工程名、工程路径,注意路径不要出现中文
设置code generator
clock generator
port
interrupt
timer
watchdog
点击generator code生成代码
二、软件代码
添加按键处理.c.h代码
key.h
#ifndef _KEY_H_ #define _KEY_H_ #include "r_cg_macrodriver.h" #include "r_cg_port.h" #include "r_cg_userdefine.h" #define COUNT_RESET 0 #define FLAG_RESET 0 #define FLAG_SET !FLAG_RESET #define LEVEL_HIGH 1 #define LEVEL_LOW 0 //注:按键按下时引脚电平是高电平还是低电平!!! // | // | // \|/ #define PRESS_LEVEL LEVEL_HIGH #define RELEASE_LEVEL LEVEL_LOW //按键引脚定义 #define KEY1_PIN KEY_M1P_IN //KEY1按键引脚 #define KEY2_PIN KEY_M1N_IN //KEY2按键引脚,按键2实际未使用!!! //键盘状态 #define KEYSTATE_0 0 //初始状态 #define KEYSTATE_1 1 //消抖状态 #define KEYSTATE_2 2 //释放状态 //按键键值 #define KEY_DEFAULT (RELEASE_LEVEL << 1 | RELEASE_LEVEL) //按键状态缺省值 0b0000_0000 //0x00 #define KEY1_VALUE (RELEASE_LEVEL << 1 | PRESS_LEVEL ) //按键1按下键值 #define KEY2_VALUE (PRESS_LEVEL << 1 | RELEASE_LEVEL) //按键2按下键值 #define KEY1_KEY2_LONG_VALUE (PRESS_LEVEL << 1 | PRESS_LEVEL ) //按键1、2长按按下键值 //长按、短按标志 #define NULL_PRESS 0 //无按键标志 #define SHORT_PRESS 1 //短按标志 #define LONG_PRESS 2 //长按标志 #define DOUBLE_SHORT_PRESS 3 //双击短按标志 //按键处理返回值 #define KEY1_SHORT 1 //按键1短按 #define KEY2_SHORT 2 //按键2短按 #define KEY1_LONG 3 //按键1长按 #define KEY2_LONG 4 //按键2长按 #define KEY1_KEY2_LONG 5 //按键1、2同时长按 #define KEY1_DOUBLE_SHORT_PRESS 6 //按键1双击短按 #define KEY2_DOUBLE_SHORT_PRESS 7 //按键2双击短按 // #define DEBOUNCE_TIME 30 //消抖延时时间,单位ms #define SHORT_PRESS_TIME 800 //判断短按时间,计时小于该值为短按,单位ms #define WRONG_PRESS_TIME 2800 //判断短按出错时间,计时大于该值表示出错,单位ms #define LONG_PRESS_TIME 5000 //判断长按时间值5秒,计时大于该值表示长按,单位ms #define SHORT_PRESS_INTERVAL 300 //连击间隔时间,单位ms #define LONG_PRESS_INTERVAL 3000 //两次长按间隔时间,单位ms // #define DOUBLE_SHORT_PRESS_COUNT (COUNT_RESET + 1) // 注:用>判断取+1,用>=判断取+2 // typedef struct { unsigned char Flag; //标志 unsigned int Count; //计数 } Variable; extern Variable KeyPress; //按键按下 extern Variable KeyLongPressInterval; //相邻两次长按间隔 extern Variable KeyShortPressInterval; //相邻两次短按间隔 extern Variable KeyShortPress; //按键短按 extern Variable KeyLongPress; //按键长按 void Key_1ms_scan(void); void KeyHandle(void); #endif
key.c
#include "key.h" //适用独立按键 Variable KeyPress; //按键按下 Variable KeyLongPressInterval; //相邻两次长按间隔 Variable KeyShortPressInterval; //相邻两次短按间隔 Variable KeyShortPress; //按键短按 Variable KeyLongPress; //按键长按 static unsigned char Key_Scan(void); static void Key1_Short_Press(void); //static void Key2_Short_Press(void); //-----------------------------key----------------------------- // 函数介绍:按键扫描 // 入口参数:/ // 出口参数:键值 // 备 注:/ static unsigned char Key_Scan(void) { static unsigned char CurrentKeyState = KEYSTATE_0; //当前键盘状态 static unsigned char CurrentKeyValue = KEY_DEFAULT; //当前键值,初始值设为无按键按下时的值,若变量初始值为0与按键按下时值相同,在长按键识别时,会连续返回长按键值,导致长按键处理出错 unsigned char LongOrShortFlag = NULL_PRESS; //长/短按标志,初始清0 unsigned char KeyPin; //所有按键引脚键值字符(单字节最多8个按键) /* 32bit series */ //KeyPin = /*(KEY2_PIN << 1) |*/ KEY1_PIN; //各键值组成一个无符号字符,按键按下时IO口的电平,松开时IO口的电平,需根据实际情况而定 /* 8bit series */ KeyPin = /*(KEY2_PIN * 2) |*/ KEY1_PIN; /* 按键按下时低电平,释放时高电平 */ //KeyPin &= KEY_DEFAULT; //读取键值 /* 按键按下时高电平,释放时低电平 */ KeyPin |= KEY_DEFAULT; //读取键值 switch(CurrentKeyState) //读取当前按键状态 { case KEYSTATE_0: //初始状态 if(KeyPin != KEY_DEFAULT) //判断有无按键 { CurrentKeyValue = KeyPin; //读取键值 CurrentKeyState = KEYSTATE_1; //初始状态转消抖状态 KeyPress.Count = COUNT_RESET; //按键按下计时清0 KeyPress.Flag = FLAG_SET; //按键按下标志置1 } break; case KEYSTATE_1: //消抖状态 if(KeyPress.Count > DEBOUNCE_TIME) //按下计时大于消抖延时时间 { if(KeyPin == CurrentKeyValue) //判断是否仍按下此键 { CurrentKeyState = KEYSTATE_2; //若是,消抖状态转释放状态,判断按键释放 } else { CurrentKeyState = KEYSTATE_0; //若否,消抖状态转初始状态,重新开始判断 } KeyPress.Count = COUNT_RESET; //按键按下计时清0 KeyPress.Flag = FLAG_RESET; //按键按下标志清0 } break; case KEYSTATE_2: //释放状态 KeyPress.Flag = FLAG_SET; //按键按下标志置1 if(KeyPin == KEY_DEFAULT) //若按键释放 { if(KeyLongPress.Flag) //若是长按键释放 { KeyLongPress.Flag = FLAG_RESET; //长按键标志清0 } else //若是短按释放 { //双击 /*if(KeyPress.Count < SHORT_PRESS_TIME) //按下计时小于短按设定(最长)时间 { KeyShortPress.Count++; //短按计数+1 if(KeyShortPressInterval.Flag == FLAG_RESET) //短按间隔计时标志为0时 { KeyShortPressInterval.Flag = FLAG_SET; //短按间隔计时标志置1,开始计时 } else { ; } } else if(KeyPress.Count > WRONG_PRESS_TIME) //按下计时大于出错判断设定时间 { LongOrShortFlag = NULL_PRESS; //判断为出错动作,认为无按键 }*/ //单击 if(KeyPress.Count < SHORT_PRESS_TIME) //按下计时小于短按设定(最长)时间 { LongOrShortFlag = SHORT_PRESS; //判断为短按(单击)动作 } else if(KeyPress.Count > WRONG_PRESS_TIME) //按下计时大于出错判断设定时间 { LongOrShortFlag = NULL_PRESS; //判断为出错动作,认为无按键 } } KeyLongPressInterval.Flag = FLAG_RESET; //长按间隔计时标志清0 KeyPress.Flag = FLAG_RESET; //按键按下标志清0 KeyPress.Count = COUNT_RESET; //按键按下计数清0 CurrentKeyState = KEYSTATE_0; //转初始状态 } else if(KeyPin == CurrentKeyValue) //判断是否仍按下此键 { if(KeyPress.Count >= LONG_PRESS_TIME) //按下计时大于长按设定时间 { KeyPress.Count = LONG_PRESS_TIME; // LongOrShortFlag = LONG_PRESS; //判断为长按动作 KeyLongPress.Flag = FLAG_SET; //按键长按标志置1 } } break; default: break; } //双击 /*if(KeyShortPressInterval.Count > SHORT_PRESS_INTERVAL) //短按间隔计时大于设定时间 { if(KeyShortPress.Count > DOUBLE_SHORT_PRESS_COUNT) //短按计数大于设定次数(双击大于1次) { LongOrShortFlag = DOUBLE_SHORT_PRESS; //判断为双击短按动作 } else //短按计数小于设定次数 { LongOrShortFlag = SHORT_PRESS; //判断为短按(单击)动作 } KeyShortPressInterval.Flag = FLAG_RESET; //短按间隔计时标志清0 KeyShortPressInterval.Count = COUNT_RESET; //短按间隔计数清0 KeyShortPress.Count = COUNT_RESET; //短按计数清0 }*/ if(LongOrShortFlag != NULL_PRESS) //有键按下,长/短一起处理 { switch(CurrentKeyValue) //识别键值 //(KEY2<<1 | KEY1) { case KEY1_VALUE: if(LongOrShortFlag == DOUBLE_SHORT_PRESS) //双击短按动作 { return KEY1_DOUBLE_SHORT_PRESS; // 双击返回值 } else if(LongOrShortFlag == SHORT_PRESS) //短按动作 { KeyLongPressInterval.Flag = FLAG_RESET; //长按间隔计时标志清0 return KEY1_SHORT; //短按返回值 } else if((LongOrShortFlag == LONG_PRESS) && (KeyLongPressInterval.Flag == FLAG_RESET)) //连续长按按键 { KeyLongPressInterval.Flag = FLAG_SET; //长按间隔计时标志置1 KeyPress.Count = COUNT_RESET; //按键按下计时清0 // if(KeyLongPressInterval.Count > LONG_PRESS_INTERVAL) // { // KeyLongPressInterval.Count = COUNT_RESET; // KeyLongPressInterval.Flag = FLAG_RESET; return KEY1_LONG; //长按返回值 // } } if(KeyLongPressInterval.Count > LONG_PRESS_INTERVAL) //长按间隔计时大于设定时间 { KeyLongPressInterval.Flag = FLAG_RESET; //长按间隔计时标志清0 KeyLongPressInterval.Count = COUNT_RESET; //长按间隔计时清0 } break; case KEY2_VALUE: if(LongOrShortFlag == DOUBLE_SHORT_PRESS) //双击短按动作 { return KEY2_DOUBLE_SHORT_PRESS; //双击返回值 } else if(LongOrShortFlag == SHORT_PRESS) //短按动作 { KeyLongPressInterval.Flag = FLAG_RESET; return KEY2_SHORT; //短按返回值 } else if((LongOrShortFlag == LONG_PRESS) && (KeyLongPressInterval.Flag == FLAG_RESET)) //连续长按按键 { KeyLongPressInterval.Flag = FLAG_SET; KeyPress.Count = COUNT_RESET; // if(KeyLongPressInterval.Count > LONG_PRESS_INTERVAL) // { // KeyLongPressInterval.Count = COUNT_RESET; // KeyLongPressInterval.Flag = FLAG_RESET; return KEY2_LONG; //长按返回值 // } } if(KeyLongPressInterval.Count > LONG_PRESS_INTERVAL) //长按间隔计时大于设定时间 { KeyLongPressInterval.Flag = FLAG_RESET; //长按间隔计时标志清0 KeyLongPressInterval.Count = COUNT_RESET; //长按间隔计时清0 } break; case KEY1_KEY2_LONG_VALUE: if((LongOrShortFlag == LONG_PRESS) && (KeyLongPressInterval.Flag == FLAG_RESET)) //连续长按按键 { KeyLongPressInterval.Flag = FLAG_SET; KeyPress.Count = COUNT_RESET; // if(KeyLongPressInterval.Count > LONG_PRESS_INTERVAL) // { // KeyLongPressInterval.Count = COUNT_RESET; // KeyLongPressInterval.Flag = FLAG_RESET; return KEY1_KEY2_LONG; //长按返回值 // } } if(KeyLongPressInterval.Count > LONG_PRESS_INTERVAL) //长按间隔计时大于设定时间 { KeyLongPressInterval.Flag = FLAG_RESET; //长按间隔计时标志清0 KeyLongPressInterval.Count = COUNT_RESET; //长按间隔计时清0 } break; /* case : break; case : break; ...扩展按键处理 */ default: break; } } return 0; //无键按下,返回0 } /* put the function in 1ms interrupt */ void Key_1ms_scan(void) { // Key_Value = Key_Scan(); // 按键按下计时 if(KeyPress.Flag) { if(KeyPress.Count < 65535) { KeyPress.Count++; } } else { KeyPress.Count = COUNT_RESET; } // 相邻两次长按间隔计时 if(KeyLongPressInterval.Flag) { if(KeyLongPressInterval.Count < 65535) { KeyLongPressInterval.Count++; } } else { KeyLongPressInterval.Count = COUNT_RESET; } // 相邻两次短按间隔计时 if(KeyShortPressInterval.Flag) { if(KeyShortPressInterval.Count < 65535) { KeyShortPressInterval.Count++; } } else { KeyShortPressInterval.Count = COUNT_RESET; } } static void Key1_Short_Press(void) { KeyShortPressProc(); } static void Key1_Double_Short_Press(void) { KeyDoubleShortPressProc(); } /*static void Key2_Short_Press(void) { }*/ /*static void Key1_Key2_Long_Press(void) { ; }*/ /* put the function in main.c */ void KeyHandle(void) { switch(Key_Scan()) //Key_Value { case KEY1_SHORT: Key1_Short_Press(); break; /*case KEY2_SHORT: Key2_Short_Press(); break;*/ //双击 //case KEY1_DOUBLE_SHORT_PRESS: // Key1_Double_Short_Press(); // break; /* case KEY1_KEY2_LONG: Key1_Key2_Long_Press(); break; case : break; case : break; ...add key hanlde */ default: break; } }
需注意的是,工程中使用P122引脚作为INTP2功能,而芯片默认使用P13引脚,因此需要设置IO重定向寄存器
void R_Systeminit(void) { PIOR = 0x01U;//PIOR = 0x00U; // 允许INTP2引脚重定向 R_CGC_Get_ResetSource(); R_CGC_Create(); R_PORT_Create(); R_TAU0_Create(); R_WDT_Create(); R_INTC_Create(); IAWCTL = 0x00U; }
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 INTP2 low priority */ PPR12 = 1U; PPR02 = 1U; EGP0 = _04_INTP2_EDGE_RISING_SEL; /* Set INTP2 pin */ //PMC1 &= 0xF7U; //INTP2引脚重定向后删除 //PM1 |= 0x08U; }
三、工程文件
https://files.cnblogs.com/files/Jayisingraduateschool/20231219%E5%8D%95%E5%87%BB.zip?t=1703343815&download=true
标签:Count,RESET,void,R5F1026A,笔记,瑞萨,按键,PRESS,KeyLongPressInterval From: https://www.cnblogs.com/Jayisingraduateschool/p/17922555.html