历史上的今天
今天是:2024年09月22日(星期日)
2020年09月22日 | 关于按键扫描程序的终极讨论
2020-09-22 来源:eefocus
一、思路
基于STM8,按键处理,思路是这样的:
每20ms左右一次去扫描按键,用一个key_now记录当前值,用key_last记录上次的值,如果key_now和key_last同时有效,则开始进行cnt++。
我设定两个阈值,LONG_PRESS为100(100*20ms=2s),SHORT_PRESS为4(4*20ms=80ms,去抖)。
cnt大于LONG_PRESS,表示是长按,反之再判断cnt是不是大于SHORT_PRESS,表示是短按,否则把cnt清零。
另外一种情况,我们在设置参数的时候,要不停加1或者减1,我长按,希望数值连续增减,怎么实现?
接上面的cnt值,再设置一个连按的阈值,MID_PRESS=50(50*20ms=1s)。
当cnt大于MID_PRESS时,我认为触发了短按,但此时不清空cnt,只是将cnt减去SHORT_PRESS的值。
如此下去,如果按键一直不松开,则一直连线触发短按。
二、实现
硬件上有三个按键,分别是set,up,down。
// 控制按键时长
#define LONG_PRESS 100 // 20ms*100=2s,长按
#define SHORT_PRESS 5 // 20ms*5=100ms,短按
#define MID_PRESS 50 // 20ms*50=1s,连按
#define REPEAT_PRESS 5 // 200ms*5=100ms,连按灵敏参数
#define KEY_PORT (GPIOC)
#define KEY_SET (GPIO_PIN_5) // set键接PC5
#define KEY_UP (GPIO_PIN_6) // up键接PC6
#define KEY_DOWN (GPIO_PIN_7) // down键接PC7
uchar pinNow;
bool pinSet_now, pinUp_now, pinDown_now;
bool pinSet_last, pinUp_last, pinDown_last;
bool set_long = FALSE; // set键长按
bool set_short = FALSE; // set键短按
bool up_short = FALSE; // up键短按
bool down_short = FALSE; // down键短按
// 初始化
void key_proc_init(void)
{
GPIO_Init(KEY_PORT, KEY_SET|KEY_UP|KEY_DOWN, GPIO_MODE_IN_FL_IT);
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_FALL_ONLY);
pinNow = 0;
set_cnt = 0;
up_cnt = 0;
down_cnt = 0;
set_long = FALSE;
set_short = FALSE;
up_short = FALSE;
down_short = FALSE;
}
// 按键处理
void key_scan(void)
{
//按键端口上拉了,默认是高电平,有按键时变低。这里取反,有按键时变高。
pinNow = 0xFF - GPIO_ReadInputData(KEY_PORT);
pinSet_now = pinNow & KEY_SET;
pinUp_now = pinNow & KEY_UP;
pinDown_now = pinNow & KEY_DOWN;
// set键只分长按和短按,没有连按
if (pinSet_now & pinSet_last) {
set_cnt++;
if (set_cnt>LONG_PRESS) {
set_long = TRUE;
set_cnt = 0;
}
}else {
if (set_cnt>SHORT_PRESS) {
set_short = TRUE;
set_cnt = 0;
}else{
set_cnt = 0;
}
}
// up和down键有连按和短按,没有长按
if (pinUp_now & pinUp_last) {
up_cnt++;
if (up_cnt>MID_PRESS) {
up_short = TRUE;
up_cnt = up_cnt - REPEAT_PRESS;
}
}else{
if (up_cnt>SHORT_PRESS) {
up_short = TRUE;
up_cnt = 0;
}
}
if (pinDown_now & pinDown_last) {
down_cnt++;
if (down_cnt>MID_PRESS) {
down_short = TRUE;
down_cnt = down_cnt - REPEAT_PRESS;
}
}else{
if (down_cnt>SHORT_PRESS) {
down_short = TRUE;
down_cnt = 0;
}
}
// 添加自己对于set_long,set_short,up_short,down_short的处理代码
// 处理完了不要忘记把相应的值置为FALSE
pinSet_last = pinSet_now;
pinUp_last = pinUp_now;
pinDown_last = pinDown_now;
}
然后用定时器中断,每20ms去执行一个key_scan()函数。
上一篇:规范的位操作方法
史海拾趣
|
想像一下,如果有这么一个“裸体”温度计,就放在自己家里的书柜上,等朋友来了,一定会吸引不少眼光,你也可以借机炫耀一番。 不过放在家里的话,有可能曝光率不够高,那我们就随身携带好了,就像劳力士一样,经常“不经意”的掏出来看看:P ...… 查看全部问答> |
|
6月份参加了比赛,拿了个三等奖,用STM32做的东西,等出差回去把所有东西开源出来,给大家一个参考 包括: 无线模块 红外通信 GPRS短信 屏幕驱动 vs1003驱动等等… 查看全部问答> |
|
找工作,大家帮忙介绍下工作啊,上海或者苏州,南京周围的,Windows Mobile 或者Android的应用程序开发啊! RT,本人有一年的Windows Mobile和Android的开发经验。谢谢各位啦!… 查看全部问答> |
|
PlatForm Builder 5.0 难道就是Windows CE 5.0 ? 如题,PlatForm Builder 5.0难道就是Windows CE 5.0? 我在电驴上看PlatForm Builder 5.0有2.6G大,但是这个源已经不全了。 http://board.verycd.com/t252175.html 但是微软 http://www.microsoft.com/downloads/details.aspx?familyid=486E825 ...… 查看全部问答> |
|
我已经加了Dial Up Networking (RAS/PPP) 的支持,wince可以建立PPPoE拨号了,但是每次拨号时候都提示“PPPoE访问集中器无响应”。 请问是怎么回事情?要怎么样才能拨号,麻烦兄弟们指点一下。 谢谢了。… 查看全部问答> |




