程序运行效果说明
按下KEY1,数码管上的示数加1。
按下KEY2,数码管上的示数减1。
程序电路工作原理以及按键抖动原因
当按键被按下的时候,电路导通接地,I/O口为低电平;当按键未被下时,电路断开,I/O口保持高电平。但一般的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,假如不加以处理,会导致按键被识别为按下多次。为了不产生这种现象而作的措施就是按键消抖。
消抖的方法
按键消抖分为硬件消抖和软件消抖
1.硬件消抖
在键数较少时可用硬件方法消除抖动。下图所示的RS触发器为常用的硬件去抖。
图中两个“与非”门构成一个RS触发器。当按键未按下时,输出为0;当键按下时,输出为1。此时即使用按键的机械性能,使按键因弹性抖动而产生瞬时断开(抖动跳开B),只要按键不返回原始状态A,双稳态电路的状态不改变,输出保持为0,不会产生抖动的波形。也就是说,即使B点的电压波形是抖动的,但经双稳态电路之后,其输出为正规的矩形波。这一点通过分析RS触发器的工作过程很容易得到验证。
2.软件消抖
方法1:使用延时
如果按键较多,常用软件方法去抖,即检测出键闭合后执行一个延时程序,5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。
方法2:检测多次
可以设定一个检测周期,如果在一个检测周期内,按键被检测为被按下达到了一定的次数,则确认为真正的被按下。
#include "STC15F2K60S2.h"
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
//数码管段选信号 从0到9
uchar code duanxuan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//数码管位选信号 显示在第4到7位
uchar code weixuan[4]={0x04,0x05,0x06,0x07};
sbit led_sel=P2^3;//74HC138 的一个使能位
sbit key1=P3^2;//按键k1
sbit key2=P3^3;//按键k2
uint number;//显示在数码管上的值
uint flag;//位选的位置
int count1,count2,count3,count4;//用于消抖计数
bit status_P,status_P2;//记录按键前一状态
void Init()
{//将P0设置成推挽输出 P2的低四位设置成推挽输出 P3不需要设置成推挽输出
P0M0=0XFF;
P0M1=0X00;
P2M0=0X0F;
P2M1=0X00;
led_sel=0;
P0=0;
number=5000;//初始化number=5000
count1=0;
count2=0;
count3=0;
count4=0;
status_P=0;
status_P2=0;
flag=0;
TMOD=0X00;
EA=1;
ET0=1;
TH0=(65536-200)/256;
TL0=(65536-200)%256;
TR0=1;
}
void InterruptTimer0()interrupt 1
{
switch(flag)
{
case 0:P0=0;P2=weixuan[flag];P0=duanxuan[number/1000];break;
case 1:P0=0;P2=weixuan[flag];P0=duanxuan[(number/100)%10];break;
case 2:P0=0;P2=weixuan[flag];P0=duanxuan[(number%100)/10];break;
case 3:P0=0;P2=weixuan[flag];P0=duanxuan[(number%100)%10];break;
}
flag++;
count1++;
if(key1==0)
count2++;
count3++;
if(key2==0)
count4++;
}
void main()
{
Init();
while(1)
{
if(flag==4)//修正位选位置 可放在中断程序外 放在中断外 效果更好
flag=0;
if(count1==30)//消抖大概6ms 总共统计次数 30次
{
if(count2>=20)// 如果低电平的有效次数为 2/3 以上
{
if(status_P==1)
{
status_P=0;
number++;
}
}
else
status_P=1;
count1=0;
count2=0;
}
if(count3==30)//消抖大概6ms 总共统计次数 60次
{
if(count4>=20)// 如果低电平的有效次数为 2/3 以上
{
if(status_P2==1)
{
status_P2=0;
number--;
}
}
else
status_P2=1;
count3=0;
count4=0;
}
}
}