首先说明一下我这个按键扫描函数的作用,我要实现的是长按按键就关闭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。