| 
 
| 首先说明一下我这个按键扫描函数的作用,我要实现的是长按按键就关闭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 <stdbool.h>
 
 #include <stdint.h>
 
 #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() {
 
 // 执行两个按键同时按下的操作
 
 }
 
 
 
 | 
 |