[分享]简单的按键扫描程序
分享一个简单的按键扫描程序,方便有需要的用户搜索参考。例程使用定时器分时调度,定时每毫秒检测一次按键状态,有按键时累加计数器,没有按键时清除计数器。
连续计数50次表明按键按下并持续50ms(防抖),设置按键有效状态标志:
if(!KEY1)
{
if(!Key1_Flag)
{
Key1_cnt++;
if(Key1_cnt >= 50) //50ms防抖
{
Key1_Flag = 1; //设置按键状态,防止重复触发
Key1_Function = 1;
}
}
}
else
{
Key1_cnt = 0;
Key1_Flag = 0;
}
检测连续1s为低电平则判定按键长按有效;连续低电平时间大于50ms并小于1s则判定为按键短按有效:
if(!KEY2)
{
if(!Key2_Flag)
{
Key2_cnt++;
if(Key2_cnt >= 1000) //长按1s
{
Key2_Short_Flag = 0; //清除短按标志
Key2_Long_Flag = 1; //设置长按标志
Key2_Flag = 1; //设置按键状态,防止重复触发
Key2_Long_Function = 1;
}
else if(Key2_cnt >= 50) //50ms防抖
{
Key2_Short_Flag = 1; //设置短按标志
}
}
}
else
{
if(Key2_Short_Flag) //判断是否短按
{
Key2_Short_Flag = 0; //清除短按标志
Key2_Short_Function = 1;
}
Key2_cnt = 0;
Key2_Flag = 0; //按键释放
}
}
此外,推荐一份社区大神分享的按键扫描方法介绍的帖子:
【分享】按键程序,大道至简,按键扫描 + 累计主循环次数去抖动/不占用定时器
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=5936
(出处: 国芯论坛-STC全球32位8051爱好者互助交流社区) 这种长按程序和短按程序是相互独立的,且长按程序在每次长按操作中只执行一次。(希望没有分析错误) 这种写法是不是受程序周期影响啊,程序周期不固定怎么办 zhudean11 发表于 2024-1-25 17:30
这种写法是不是受程序周期影响啊,程序周期不固定怎么办
那需要估算一下多长时间调用一次按键扫描程序,检测次数*检测周期=20~50ms左右。
这个帖子有介绍如何检测循环周期:
【分享】按键程序,大道至简,按键扫描 + 累计主循环次数去抖动/不占用定时器
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=5936 乘风飞扬 发表于 2024-1-25 18:52
那需要估算一下多长时间调用一次按键扫描程序,检测次数*检测周期=20~50ms左右。
这个帖子有介绍如何检测 ...
感谢分享,学习一下,谢谢! 感谢分享 {:4_174:}学习了 typedef union{
u8 dat;
struct{
u8 bit0:1;
u8 bit1:1;
u8 bit2:1;
u8 bit3:1;
u8 bit4:1;
u8 bit5:1;
u8 bit6:1;
u8 bit7:1;
} bits;
}Key_data;
#define Key1( P70 )
#define Key2( P71 )
#define Key3( P72 )
#define Key4( P73 )
#define Key5( P41 )
#define Key6( P42 )
voidKey_scan(void)
{
u8 i,n;
keydat.dat = 0xFF;
Write_Key();
NOP40();
Read_Key();
if( keydat.dat != 0xFF) //有按键按下
{
Key.flag = 1;
n = keydat.dat;
for(i=0; i<6; i++) //轮询找出哪个按键被按下
{
if((n & 0x01) == 0)
{
// Key.state = 1; //状态
Key.value = 2; //有效值
}
else
{
// Key.state = 0; //状态
Key.value = 0; //有效值
Key.count = 0; //次数清零
}
n = n>>1; //数据移位
}
}
else //没有按键按下
{
Key.flag = 0; //没有按键按下
for(i=0; i<6; i++)
Key.value = 0;
}
}
void Read_Key(void)
{
keydat.bits.bit0 = Key1;
keydat.bits.bit1 = Key2;
keydat.bits.bit2 = Key3 ;
keydat.bits.bit3 = Key4;
keydat.bits.bit4 = Key5;
keydat.bits.bit5 = Key6;
}
void Write_Key(void)
{
Key1 = keydat.bits.bit0;
Key2 = keydat.bits.bit1;
Key3 = keydat.bits.bit2;
Key4 = keydat.bits.bit3;
Key5 = keydat.bits.bit4;
Key6 = keydat.bits.bit5;
} 小坤 发表于 2024-2-2 13:40
typedef union{
u8 dat;
struct{
typedef struct {
u8 flag;
u8 state;
u8 value;
u16 count;
u16 Time;
}xdata Key_conf; 一楼的我认为不能使用。首先 计数没有清零!这个不是问题好解决。但是如果第一个延时到了标志变成1.但是这个时候如果按键放开了,进入中断的时候直接进入else标志被清零。我实际测试这个也是根本没法使用