我们初学者在学些写51或者类似的单片机的时候总会为了写独立按键消抖,单击,长按,多连击而苦恼,网上都是什么中断,状态机之类的写法,也各有千秋。但是经常用的无非那几种。
我也是准备了几种简单的对应方法,适用于几种人群。
以下内容均为本人学习的时间自行研究的,若有什么不对地方请多多包含。
bit click = 0;//单击标志位
u8 key=0;//按键状态
u32 count=0;//计数
void main(){
while(1){
/*按键扫描代码*/
if(P0!=0xff){ //按键按下执行
if(count==8) //消抖后拿到按键状态值(消抖时间一般10ms以内)
key = ~P0; //这里是按键按下为低电平,取反是为了下面方便判断
count++; //消抖
}else if(count>8){ //按键松开后执行
count=0; //结束计数清零
click=1; //单击标志位置1
}else
count = 0; //抖动误触清零
/*单机后处理代码*/
if(click){ //如果按键单击
if(key==0x01) //判断按键执行操作,从0000 0001 依次左移1位
//执行内容...
else if(key==0x02)
//执行内容...
else if(key==0x04)
//执行内容...
click=0; //执行完标志置0
}
delay(1); //假设主函数运行一次的时长为1ms
}
}
这里按键是P0端口8个,如果不同可以自行更改。默认高电平,按下低电平。
这里是通过估计main函数运行一次的时长来进行消抖的,只写了单击,因为估算终究是估算,后面的长按之类的时间并不能做到特别准确就不写了。
原理就是每执行一次计数加1,当到了差不多10ms的值的时候就会消抖完成,然后拿到按键状态(只适用于同一时刻一个按键按下),然后如果是抖动的话下面的else就会清空重新计数,只有在计数在消抖完成后抬起才能进入单击的处理,代码简短,适用于只追求效果的方案。
u8 click=0; //单击标志位
u8 key[8]={0,0,0,0,0,0,0,0}; //按键状态
u16 count[8]=0; //计数
void main(){
u8 i;
while(1){
for(i=0;i<8;i++){
if(!(P0&0x01<<i)){ //判断每一个按键的状态
if(count[i]==8) //消抖后拿到按键状态值(消抖时间一般10ms以内)
key[i] = 1; //这里是按键按下为低电平,取反是为了下面方便判断
count[i]++; //消抖
}else if(count[i]>8){ //按键松开后执行
count[i]=0; //结束计数清零
click=1; //单击标志位置1
}else
count[i] = 0; //抖动误触清零
}
if(click){ //如果按键单击
if(key[0]){} //判断按键执行操作,从key[0]~key[7]
//执行内容...
if(key[1]){}
//执行内容...
if(key[2]){}
//执行内容...
click=0; //执行完标志置0
}
delay(1); //假设主函数运行一次的时长为1ms
}
}
这里就是用了一个for循环进行了8次按键的扫描,来实现多按键同时判断。
这时候下面判断就可以用多个if判断,因为可能会遇到多种情况了。但是如果不用定时器来计数,终归不是太过于严谨了。
最后,因为这也是本人的第一篇文章,也不太发过多篇幅,后面会在多多分享个人的经验的,有错的地方也希望能够指点。