抗干扰矩阵键盘按键消抖

tech2025-05-06  5

最近写了一个矩阵键盘消抖的程序,主要是功能在于实现不中断主频消抖,记录一下。

 

2021.2.11

之前改了一下,松开判断还是挺重要的,主要能提升用户的按键体验,被干扰触发可能是没什么问题了,但是松开时按键会大幅抖动一下,导致按两下出现。于是设置了两个值,一个按下时间和一个松开时间。也是改到后面,脑中愈发觉得程序正在模拟一个电容按键,不同于的是前后可调。

 

结构

(1.0)结构图

 

 

(1.1)结构图

 

 

 

代码

 

键盘按下

uchar KeyTemp_Last=0,KeyN_Last=0; //键盘方案 2021.1.27 //判断占空比,如果接通计数+,断开计数-,再设置两个通断限值 //那么定时器的计数器需要能够加和减 //抬起时间 #define keyUpTime_NOM -10 #define keyUpTime_RE -20 #define keyUpTime (REISwitch?keyUpTime_NOM:keyUpTime_RE) //按下时间 #define keyDownTime_NOM 8 #define keyDownTime_RE 15 #define keyDownTime (REISwitch?keyDownTime_NOM:keyDownTime_RE) uchar keydelay_Nstop(uchar temp)//按键不中断滤波 { static uchar keyUpWait=0;//等待抬起 uchar temp_return=CheckKeyState;//状态和键值 qie[2]=100;//!!!响应误差(0.01s) if(shi[2]>0) { if((KeyTemp_Last|temp)!=KeyTemp_Last)//实时判断,对比数据,用或来消除杂波 { sub[2]=1;//定时器减法 if(keyUpWait)//按键已触发 { if(mm[2]<=keyUpTime)//2.判断断开阈值(-) KeyTemp_Last=mm[2]=shi[2]=0; } else if(mm[2]<=0)//1.5 按键未触发,判断接通阈值(-) KeyTemp_Last=mm[2]=shi[2]=0; } else { sub[2]=0;//定时器加法 if(mm[2]>=shi[2])//1.判断接通阈值(+) { temp_return=KeyTemp_Last; keyUpWait=1; mm[2]=shi[2]; } } } else { keyUpWait=0;//等待抬起 if(temp!=KeyDT) { if((temp|0xEF)==0xEF)KeyTemp_Last=0x0F;//获取键值,一行5个 if((temp|0xF7)==0xF7)KeyTemp_Last=0x17; if((temp|0xFB)==0xFB)KeyTemp_Last=0x1B; if((temp|0xFD)==0xFD)KeyTemp_Last=0x1D; if((temp|0xFE)==0xFE)KeyTemp_Last=0x1E; if(KeyTemp_Last) { shi[2]=keyDownTime+(mo>0)*8;//!!!这里设置时间 0.01S } } else temp_return=GetKeyState;//键盘选择状态 } return temp_return; }

 

主体

uchar code T_KeyValue[]={0,5,4,9,8,7,6,1,2,3,0,10,11,12,14,13,15,16,17,18,19}; uchar code T_KeyTemp[]={0,5,4,3,3,5,6,7,2,9,10,11,12,13,14,15,1}; void KeyScan_Nstop()//按键主程序 { static uchar n=0,key=0; uchar KeyValue; KeyValue=P2&KeyDT;//获取IO KeyValue=keydelay_Nstop(KeyValue);//按键判断 if(KeyValue==GetKeyState)//键盘选择,滞后获取 { if((++n)==4)n=0; KeyLineOne=(n!=0); KeyLineTwo=(n!=1); KeyLineThr=(n!=2); KeyLineFou=(n!=3); } if(KeyValue<=GotKeyState)//获得键值 { if(keydown==0) { key=T_KeyValue[T_KeyTemp[(~KeyTemp_Last)&KeyDT]+n*5];//转换键值 Form_Key(key); keydown=1; } } else//没有键值 key=keydown=0; }

 

定时器 

//***************定时器**************************** void tm0_isr()interrupt 1 //定时器0 100T=1S { uchar i; TL0 = 0x00; TH0 = 0xB8; for(i=0;i<10;i++) { if(shi[i]>0) { if(sub[i]==0)//多数判断0,可以少一个jump mm[i]++; else mm[i]--; if(qie[i]>0) //与主程序响应误差,用倒计时模式,超过则重置检测计数 qie[i]--; else mm[i]=0;//shi[i]= } } }

 

最新回复(0)