我[经验分享]按键扫描函数,松手检测

2025-10-14 02:07:29

函数, 按键扫描, Button, press

首先说明一下我这个按键扫描函数的作用,我要实现的是长按按键就关闭MCU所有外设,即进入睡眠模式,睡眠之后可以使用这个按键进行唤醒MCU,那么这里就要考虑一个误唤醒的问题,所以思路是长按之后进行一个假睡眠(我这里的表现就是关闭小灯),松手之后才会真正意义上的执行睡眠指令,开启中断,进入睡眠模式。

对于准确的应用按键,那么首先要了解按键的几种状态:

①刚开始都是松开的;

②使用时由松开到按下;

③一直按下不松开;这里还涉及到是否要连续有效还是单次有效;

④由按下到松开;

⑤一直松开;

首先说明几个变量的作用:

1、Release_cnt:松手之后或者没有按下按键进行累加,用以按下按键松手之后的消抖;

2、Presse_cnt:按键按下进行累加,消抖作用;

3、Key1_Flag:按键按下标志,设置按键状态,防止重复触发的作用;

4、Key1_Pressed:标志位,为1表示按键确认按下了;

5、Key1_Function:也是一个标志位,为1去执行相应的操作;

6、Key1_Released:标志位:为1表示按键按下有效并且确认松手了;

下面是一个大概的流程图;

下面是具体的按键扫描函数,长按关机,松手有效,单次触发;

void KeyScan(void)

{

//单纯短按按键

if(!KEY1)

{

Release_cnt = 0;

if(!Key1_Flag)

{

Presse_cnt++;

if(Presse_cnt >= 1000) //1s长按防抖

{

Key1_Flag = 1; //设置按键状态,防止重复触发

Key1_Pressed = 1;

Key1_Function = 1;

}

}

}

else

{

if(Key1_Pressed)

{

Release_cnt++;

if(Release_cnt >= 50) //50ms释放防抖

{

Key1_Pressed = 0;

Key1_Released = 1;

}

}

Presse_cnt = 0;

Key1_Flag = 0;

}

}

下面是主函数里的while循环,Key1_Function这个标志长按不松手就置1,现象就是P20引脚电平拉高,熄灭小灯;松手之后Key1_Released置1,就开启中断进入睡眠;

while (1)

{

delay_ms(1);

KeyScan();

if(Key1_Function)

{

Key1_Function = 0;

printf("Sleep Ready.\r\n");

P20 = 1; //LED OFF(关闭外设,准备进入休眠)

}

if(Key1_Released)

{

Key1_Released = 0;

printf("MCU Sleep.\r\n");

IE0 = 0; //外中断0标志位

EX0 = 1; //INT0 Enable

IT0 = 1; //INT0 下降沿中断

// IT0 = 0; //INT0 上升,下降沿中断

_nop_();

_nop_();

PCON |= 0x02; //Sleep

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

_nop_();

printf("MCU Wakeup.\r\n");

P20 = 0; //LED ON

}

}

最后注意嗷,相应的判断标志在进入之后一定要清0。

-----------------------------------------------------------分割线-------------------------------------------------------------

下面是一个新的按键扫描函数,实际主体和上面思路是一样的,只是多了一个两个按键同时按下的操作,这里所说的定时其实可以使用变量累加来替换;

我猜测这个应该会有一个问题,也就是假如你同时按下的操作很慢然后松手,会执行单个按键短按的操作;

#include

#include

#define SHORT_PRESS_TIME 100 // 短按阈值(单位:毫秒)

#define LONG_PRESS_TIME 1000 // 长按阈值(单位:毫秒)

typedef enum {

BUTTON_IDLE,

BUTTON_PRESSED,

BUTTON_SHORT_PRESS,

BUTTON_LONG_PRESS

} ButtonState;

typedef struct {

bool isPressed; // 当前按键是否被按下

uint32_t pressTime; // 按键按下时的时间

ButtonState state; // 按键的状态

} Button;

Button button1 = {false, 0, BUTTON_IDLE};

Button button2 = {false, 0, BUTTON_IDLE};

uint32_t getCurrentTime(); // 获取当前时间的函数,单位:毫秒

bool isButton1Pressed(); // 检测BUTTON1是否被按下

bool isButton2Pressed(); // 检测BUTTON2是否被按下

void handleShortPress(Button* btn);

void handleLongPress(Button* btn);

void handleSimultaneousPress();

void scanButtons()

{

uint32_t currentTime = getCurrentTime();

// 更新BUTTON1状态

if (isButton1Pressed())

{

if (!button1.isPressed)

{

button1.isPressed = true;

button1.pressTime = currentTime;

button1.state = BUTTON_PRESSED;

}

else if ((currentTime - button1.pressTime) >= LONG_PRESS_TIME)

{

button1.state = BUTTON_LONG_PRESS;

handleLongPress(&button1);

}

}

else

{

if (button1.isPressed)

{

if (button1.state == BUTTON_PRESSED && (currentTime - button1.pressTime) < LONG_PRESS_TIME)

{

button1.state = BUTTON_SHORT_PRESS;

handleShortPress(&button1);

}

button1.isPressed = false;

button1.state = BUTTON_IDLE;

}

}

// 更新BUTTON2状态

if (isButton2Pressed())

{

if (!button2.isPressed)

{

button2.isPressed = true;

button2.pressTime = currentTime;

button2.state = BUTTON_PRESSED;

}

else if ((currentTime - button2.pressTime) >= LONG_PRESS_TIME)

{

button2.state = BUTTON_LONG_PRESS;

handleLongPress(&button2);

}

}

else

{

if (button2.isPressed)

{

if (button2.state == BUTTON_PRESSED && (currentTime - button2.pressTime) < LONG_PRESS_TIME)

{

button2.state = BUTTON_SHORT_PRESS;

handleShortPress(&button2);

}

button2.isPressed = false;

button2.state = BUTTON_IDLE;

}

}

// 检查两个按键同时按下

if (button1.isPressed && button2.isPressed)

{

handleSimultaneousPress();

}

}

void handleShortPress(Button* btn) {

if (btn == &button1) {

// 执行BUTTON1短按操作

} else if (btn == &button2) {

// 执行BUTTON2短按操作

}

}

void handleLongPress(Button* btn) {

if (btn == &button1) {

// 执行BUTTON1长按操作

} else if (btn == &button2) {

// 执行BUTTON2长按操作

}

}

void handleSimultaneousPress() {

// 执行两个按键同时按下的操作

}

回复

收藏0

举报