×
嵌入式 > 技术百科 > 详情

关于按键扫描程序的终极讨论

发布时间:2023-09-11 发布时间:
|

一、思路


基于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()函数。


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
变废为宝.电话亭将变多功能5G基站?破解5G BBU集中机房建设难题.原来可以如此简单!