/***12个按键,每一个按键都会让蜂鸣器发出“嘀”的一声,
同时按下S1和S12会点亮一个LED灯,同时按下***/
#include "REG52.H"
#define const_voice_short 40
#define const_key_time 12
#define const_key_time_comb 14 //组合按键去抖动延时时间
void initial_myself();
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void T0_time();
void key_service();
void key_scan();
/*
任意两个组合按键不能处于同一行,否则触发性能大打折扣。
做产品的时候,在硬件电路设计中,除了四路行输入要加上拉电阻外,
四路列输出也应该串入一个470欧左右的限流电阻,否则当一行的两个
按键同时按下时,很容易烧坏单片机的IO口。
*/
sbit key_sr1=P0^1; //第一行输入
sbit key_sr2=P0^2; //第二行输入
sbit key_sr3=P0^3; //第三行输入
sbit key_dr1=P0^4; //第一列输出
sbit key_dr2=P0^5; //第二列输出
sbit key_dr3=P0^6; //第三列输出
sbit key_dr4=P0^7; //第四列输出
sbit led_dr=P3^5; //LED灯
sbit beep_dr=P1^5;
unsigned char ucKeyStep=1; //按键扫描步骤变量
unsigned char ucKeySec=0; //被触发的按键编号
unsigned int uiKeyTimeCnt[12]=0; //12个按键去抖动延时计数器
unsigned char ucKeyLock[12]=0; //12个按键触发后自锁的变量标志
unsigned int uiKeyTimeCnt_01_12=0; //S1和S12组合按键去抖动延时计数器
unsigned char ucKeyLock_01_12=0; //S1和S12组合按键触发后自锁的变量标志
unsigned int uiKeyTimeCnt_04_09=0; //S4和S9组合按键去抖动延时计数器
unsigned char ucKeyLock_04_09=0; //Ss和S9组合按键触发后自锁的变量标志
unsigned int uiListRecord=1; //记录当前扫描到了第几列
unsigned int uiVoiceCnt=0; //蜂鸣器鸣叫的时间计数器
unsigned int uiKeyStatus=0xfff; //此变量每一位代表一个按键的状态,共12个按键。1代表没有被按下,0代表被按下
void main()
{
initial_myself();
delay_long(100);
initial_peripheral();
while(1)
{
key_service();
}
}
void key_scan() //按键扫描函数,放到定时中断里
{
/*
第一步:先把16个按键翻译成独立按键。
第二步:再按独立按键的去抖动方式进行按键识别
第三步:参考独立按键的方式,来实现组合按键
*/
switch(ucKeyStep)
{
case 1: //把12个按键的状态快速记录在uiKeyStatus变量的每一位中,相当于把矩阵键盘翻译成独立按键
for(uiListRecord=1;uiListRecord<5;uiListRecord++)
{
if(uiListRecord==1) //第一列低电平
{
key_dr1=0;
key_dr2=1;
key_dr3=1;
key_dr4=1;
//如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
if(key_sr1==0)
uiKeyStatus=uiKeyStatus&0xffe; //S1被按下
if(key_sr2==0)
uiKeyStatus=uiKeyStatus&0xfef; //S5被按下
if(key_sr3==0)
uiKeyStatus=uiKeyStatus&0xeff; //S9被按下
}
else if(uiListRecord==2) //第二列低电平
{
key_dr1=1;
key_dr2=0;
key_dr3=1;
key_dr4=1;
//如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
if(key_sr1==0)
uiKeyStatus=uiKeyStatus&0xffd; //S2被按下
if(key_sr2==0)
uiKeyStatus=uiKeyStatus&0xfdf; //S6被按下
if(key_sr3==0)
uiKeyStatus=uiKeyStatus&0xdff; //S10被按下
}
else if(uiListRecord==3) //第三列低电平
{
key_dr1=1;
key_dr2=1;
key_dr3=0;
key_dr4=1;
//如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
if(key_sr1==0)
uiKeyStatus=uiKeyStatus&0xffb; //S3被按下
if(key_sr2==0)
uiKeyStatus=uiKeyStatus&0xfbf; //S7被按下
if(key_sr3==0)
uiKeyStatus=uiKeyStatus&0xbff; //S11被按下
}
else //第四列低电平
{
key_dr1=1;
key_dr2=1;
key_dr3=1;
key_dr4=0;
//如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态
if(key_sr1==0)
uiKeyStatus=uiKeyStatus&0xff7; //S4被按下
if(key_sr2==0)
uiKeyStatus=uiKeyStatus&0xf7f; //S8被按下
if(key_sr3==0)
uiKeyStatus=uiKeyStatus&0x7ff; //S12被按下
}
}
ucKeyStep=2; //切换到下一运行步骤
break;
case 2: //像独立按键一样进行去抖动和翻译。
if((uiKeyStatus&0x001)==0x001) //说明1号按键没有被按下
{
uiKeyTimeCnt[0]=0;
ucKeyLock[0]=0;
}
else if(ucKeyLock[0]==0)
{
uiKeyTimeCnt[0]++;
if(uiKeyTimeCnt[0]>const_key_time)
{
uiKeyTimeCnt[0]=0;
ucKeyLock[0]=1; //自锁按键,防止不断触发
ucKeySec=1; //触发号按键
}
}
if((uiKeyStatus&0x002)==0x002) //说明2号按键没有被按下
{
uiKeyTimeCnt[1]=0;
ucKeyLock[1]=0;
}
else if(ucKeyLock[1]==0)
{
uiKeyTimeCnt[1]++;
if(uiKeyTimeCnt[1]>const_key_time)
{
uiKeyTimeCnt[1]=0;
ucKeyLock[1]=1; //自锁按键,防止不断触发
ucKeySec=2; //触发2号按键
}
}
if((uiKeyStatus&0x004)==0x004) //说明3号按键没有被按下
{
uiKeyTimeCnt[2]=0;
ucKeyLock[2]=0;
}
else if(ucKeyLock[2]==0)
{
uiKeyTimeCnt[2]++;
if(uiKeyTimeCnt[2]>const_key_time)
{
uiKeyTimeCnt[2]=0;
ucKeyLock[2]=1; //自锁按键,防止不断触发
ucKeySec=3; //触发3号按键
}
}
if((uiKeyStatus&0x008)==0x00) //说明4号按键没有被按下
{
uiKeyTimeCnt[3]=0;
ucKeyLock[3]=0;
}
else if(ucKeyLock[3]==0)
{
uiKeyTimeCnt[3]++;
if(uiKeyTimeCnt[3]>const_key_time)
{
uiKeyTimeCnt[3]=0;
ucKeyLock[3]=1; //自锁按键,防止不断触发
ucKeySec=4; //触发4号按键
}
}
if((uiKeyStatus&0x010)==0x010) //说明5号按键没有被按下
{
uiKeyTimeCnt[4]=0;
ucKeyLock[4]=0;
}
else if(ucKeyLock[4]==0)
{
uiKeyTimeCnt[4]++;
if(uiKeyTimeCnt[4]>const_key_time)
{
uiKeyTimeCnt[4]=0;
ucKeyLock[4]=1; //自锁按键,防止不断触发
ucKeySec=5; //触发5号按键
}
}
if((uiKeyStatus&0x020)==0x020) //说明6号按键没有被按下
{
uiKeyTimeCnt[5]=0;
ucKeyLock[5]=0;
}
else if(ucKeyLock[5]==0)
{
uiKeyTimeCnt[5]++;
if(uiKeyTimeCnt[5]>const_key_time)
{
uiKeyTimeCnt[5]=0;
ucKeyLock[5]=1; //自锁按键,防止不断触发
ucKeySec=6; //触发6号按键
}
}
if((uiKeyStatus&0x040)==0x040) //说明7号按键没有被按下
{
uiKeyTimeCnt[6]=0;
ucKeyLock[6]=0;
}
else if(ucKeyLock[6]==0)
{
uiKeyTimeCnt[6]++;
if(uiKeyTimeCnt[6]>const_key_time)
{
uiKeyTimeCnt[6]=0;
ucKeyLock[6]=1; //自锁按键,防止不断触发
ucKeySec=7; //触发7号按键
}
}
if((uiKeyStatus&0x080)==0x080) //说明8号按键没有被按下
{
uiKeyTimeCnt[7]=0;
ucKeyLock[7]=0;
}
else if(ucKeyLock[7]==0)
{
uiKeyTimeCnt[7]++;
if(uiKeyTimeCnt[7]>const_key_time)
{
uiKeyTimeCnt[7]=0;
ucKeyLock[7]=1; //自锁按键,防止不断触发
ucKeySec=8; //触发8号按键
}
}
if((uiKeyStatus&0x100)==0x100) //说明9号按键没有被按下
{
uiKeyTimeCnt[8]=0;
ucKeyLock[8]=0;
}
else if(ucKeyLock[8]==0)
{
uiKeyTimeCnt[8]++;
if(uiKeyTimeCnt[8]>const_key_time)
{
uiKeyTimeCnt[8]=0;
ucKeyLock[8]=1; //自锁按键,防止不断触发
ucKeySec=9; //触发9号按键
}
}
if((uiKeyStatus&0x200)==0x200) //说明10号按键没有被按下
{
uiKeyTimeCnt[9]=0;
ucKeyLock[9]=0;
}
else if(ucKeyLock[9]==0)
{
uiKeyTimeCnt[9]++;
if(uiKeyTimeCnt[9]>const_key_time)
{
uiKeyTimeCnt[9]=0;
ucKeyLock[9]=1; //自锁按键,防止不断触发
ucKeySec=10; //触发10号按键
}
}
if((uiKeyStatus&0x400)==0x400) //说明11号按键没有被按下
{
uiKeyTimeCnt[10]=0;
ucKeyLock[10]=0;
}
else if(ucKeyLock[10]==0)
{
uiKeyTimeCnt[10]++;
if(uiKeyTimeCnt[10]>const_key_time)
{
uiKeyTimeCnt[10]=0;
ucKeyLock[10]=1; //自锁按键,防止不断触发
ucKeySec=11; //触发11号按键
}
}
if((uiKeyStatus&0x800)==0x800) //说明12号按键没有被按下
{
uiKeyTimeCnt[11]=0;
ucKeyLock[11]=0;
}
else if(ucKeyLock[11]==0)
{
uiKeyTimeCnt[11]++;
if(uiKeyTimeCnt[11]>const_key_time)
{
uiKeyTimeCnt[11]=0;
ucKeyLock[11]=1; //自锁按键,防止不断触发
ucKeySec=12; //触发12号按键
}
}
if((uiKeyStatus&0x801)==0x000) //S1和S12的组合按键被按下
{
if(ucKeyLock_01_12==0)
{
uiKeyTimeCnt_01_12++;
if(uiKeyTimeCnt_01_12>const_key_time_comb)
{
uiKeyTimeCnt_01_12=0;
ucKeyLock_01_12=1;
ucKeySec=13; //触发13号组合按键
}
}
}
else
{
uiKeyTimeCnt_01_12=0;
ucKeyLock_01_12=0;
}
if((uiKeyStatus&0x108)==0x000) //S4和S9的组合按键被按下
{
if(ucKeyLock_04_09==0)
{
uiKeyTimeCnt_04_09++;
if(uiKeyTimeCnt_04_09>const_key_time_comb)
{
uiKeyTimeCnt_04_09=0;
ucKeyLock_04_09=1;
ucKeySec=14; //触发14号组合按键
}
}
}
else
{
uiKeyTimeCnt_04_09=0;
ucKeyLock_04_09=0;
}
uiKeyStatus=0xfff; //及时恢复状态,方便下一次扫描
ucKeyStep=1; //返回第一步
break;
}
}
void key_service() //第三区,按键服务应用程序
{
switch(ucKeySec)
{
case 1:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 2:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 3:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 4:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 5:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 6:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 7:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 8:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 9:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 10:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 11:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 12:
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 13:
led_dr=0; //LED亮
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
case 14:
led_dr=1; //LED灭
uiVoiceCnt=const_voice_short;
ucKeySec=0;
break;
}
}
void T0_time() interrupt 1
{
TF0=0;
TR0=0;
key_scan();
if(uiVoiceCnt!=0)
{
uiVoiceCnt--;
beep_dr=0;
}
else
{
;
beep_dr=1;
}
TH0=0xf8;
TL0=0x2f;
TR0=1;
}
void delay_long(unsigned int uiDelayLong)
{
unsigned int i;
unsigned int j;
for(i=0;i<uiDelayLong;i++)
for(j=0;j<500;j++)
;
}
void initial_myself()
{
beep_dr=1;
TMOD=0x01;
TH0=0xf8;
TL0=0x2f;
}
void initial_peripheral()
{
EA=1;
ET0=1;
TR0=1;
}
原文地址:https://www.cnblogs.com/TheFly/p/12003797.html