本帖最后由 k1990 于 2015-4-29 00:58 编辑
自己模仿别人程序改写的单片机独立按键同时实现单击,双击,双击蜂鸣器操作,单击led灯点亮。反复运行几次就会出现双击变成单击。用的是郭天祥的51开发板。不知道程序哪里出现问题。还是按键有问题。
/*独立按键实现单双击功能*/
#include <reg52.h>
#define const_Voice_short 40 //设定蜂鸣器短鸣累计次数
#define const_Voice_long 80 //设定蜂鸣器长鸣累计次数
#define const_KeyTime1 30//按键延时计数器实现延时去抖
#define const_KeyTime2 30//可以设置按键响应时间
#define const_Key_interval_Time1 200
#define const_Key_interval_Time2 200
void initial_Myself();//初始化
void initial_Peripheral();//初始化外部器件
void Delay_long(unsigned int uiDelaylong);
void Key_scan();//
void Key_service();
void T0_time();
sbit beep_dr=P2^3;
sbit led0_dr=P1^0;
sbit led1_dr=P1^1;
sbit Key1_sr=P3^6;//s4键
sbit Key2_sr=P3^7;//s5键
unsigned char ucKeynum=0;//判断按键
unsigned int uiVoiceCnt=0;//蜂鸣器延时计数器
unsigned char ucKeycnt1=0;//按键次数计数器
unsigned int uiKeyTimeCnt1=0;//按键延时计数器
unsigned char ucKeylock1=0;//按键s2自锁标志
unsigned int uiKeyintervalCnt1=0;//按键时间间隔计数器
unsigned char ucKeycnt2=0;//按键次数计数器
unsigned int uiKeyTimeCnt2=0;
unsigned char ucKeylock2=0;
unsigned int uiKeyintervalCnt2=0;//按键时间间隔计数器
void main()
{
initial_Myself();
Delay_long(100);
initial_Peripheral();
while(1)
{
Key_service();
}
}
void Key_scan()
{
if(Key1_sr==1)//判断按键1是否按下,没有按下清空按键延时计数器和按键自锁标志
{
ucKeylock1=0;
uiKeyTimeCnt1=0;//累计中断次数计数器清零
if(ucKeycnt1>0)//已经按键一次,可能触发双击
{
uiKeyintervalCnt1++;//按键时间间隔计数器开始累加
if(uiKeyintervalCnt1>const_Key_interval_Time1)//超过有效间隔时间
{
uiKeyintervalCnt1=0;//时间间隔计数器清零
ucKeycnt1=0;//按键次数清零
ucKeynum=3;
}
}
}
else if(ucKeylock1==0)
{
++uiKeyTimeCnt1;
if(uiKeyTimeCnt1>const_KeyTime1)//延时去抖
{
uiKeyTimeCnt1=0;
ucKeylock1=1;
ucKeycnt1++;//按键次数加1
if(ucKeycnt1>1)
{
ucKeycnt1=0;
ucKeynum=1;
}
}
}
if(Key2_sr==1)//判断按键2是否按下,没有按下清空按键延时计数器和按键自锁标志
{
ucKeylock2=0;
uiKeyTimeCnt2=0;
if(ucKeycnt2>0)//已经按键一次,可能触发双击
{
uiKeyintervalCnt2++;//按键时间间隔计数器开始累加
if(uiKeyintervalCnt2>const_Key_interval_Time2)//超过有效间隔时间
{
uiKeyintervalCnt2=0;//时间间隔计数器清零
ucKeycnt2=0;//按键次数清零
ucKeynum=4;
}
}
}
else if(ucKeylock2==0)
{
++uiKeyTimeCnt2;
if(uiKeyTimeCnt2>const_KeyTime2)//延时去抖
{
uiKeyTimeCnt2=0;
ucKeylock2=1;
ucKeycnt2++;//按键次数加1
if(ucKeycnt2>1)
{
ucKeycnt2=0;
ucKeynum=2;
}
}
}
}
void Key_service()
{
switch(ucKeynum)
{
case 1:
uiVoiceCnt=const_Voice_short;
ucKeynum=0;
break;
case 2:
uiVoiceCnt=const_Voice_long;
//uiVoiceCnt=const_Voice_short;
ucKeynum=0;
break;
case 3:
//uiVoiceCnt=const_Voice_long;
//uiVoiceCnt=const_Voice_short;
led0_dr=~led0_dr;
ucKeynum=0;
break;
case 4:
//uiVoiceCnt=const_Voice_long;
//uiVoiceCnt=const_Voice_short;
led1_dr=~led1_dr;
ucKeynum=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; //重装初始值(65535-2000)=63535=0xf82f
TL0=0x2f;
TR0=1; //开中断
}
/* 注释:
* C51的中断函数格式如下:
* void 函数名() interrupt 中断号
* {
* 中断程序内容
* }
* 函数名可以随便取,只要不是编译器已经征用的关键字。
* 这里最关键的是中断号,不同的中断号代表不同类型的中断。
* 定时中断的中断号是 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;//关闭蜂鸣器
led0_dr=1;
led1_dr=1;
//Key_gnd_sr=0;
TMOD=0X01;
TH0=0xf8; //重装初始值(65535-2000)=63535=0xf82f
TL0=0x2f;
}
void initial_Peripheral()
{
EA=1; //开总中断
ET0=1; //允许定时中断
TR0=1; //启动定时中断
}
|