这程序是在本论坛找到的,原设定是按一下LED1亮一秒灭,按两下LED2亮一秒灭,长按LED3亮一秒灭。试验后发现有时按两下是LED1亮一秒灭,不知这程序怎样修改避免发生这种情况,谢谢!
//51单片机识别 "单击.双击.长按" 代码
//作者:Kxuan163
//程序功能:检测按钮的按下弹起次数,以识别"单击.双击.长按"
//MCU: STC89c52RC 晶振 11.0592MHZ
//Proteus8仿真通过;51开发板实验通过。
#include<reg52.h>
#include<stdlib.h>
sbit button =P1^2; //按钮连接的单片机引脚
sbit LED1 =P2^7; //单击则LED1亮
sbit LED2 =P2^4; //双击则LED2亮
sbit LED3 =P2^0; //长按则LED3亮
unsigned char count; //T0计数溢出中断次数
unsigned char finish; //T0计时一轮结束标志
unsigned char read; //读取P1^2引脚电平的变量
unsigned char dn; //读得P1^2引脚低电平次数
unsigned char up; //button弹起次数
//延时函数,入口参数ms为延时的毫秒数/////
void delayms(unsigned int ms)
{ unsigned char i;
while(ms--)
{ for(i = 0; i < 120; i++); }
} //////////////////////////////////////
//主函数
void main(void)
{
//T0 初始化 //////////////////////////
TMOD=0x01; //使用定时器T0的模式1
TH0=(65536-46083)/256; //定时器T0的高8位设置初值
TL0=(65536-46083)%256; //定时器T0的低8位设置初值
EA=1; //开总中断
ET0=1; //T0中断允许
//////////////////////////////////////
while(1)
{
LED1 =1; LED2=1; LED3=1;
dn =0; up=0; count =0; finish =0;
TR0=1; //启动T0计时
while(finish !=1 ) //在设定的T0计时段内循环检测
{
read =button; //读取P1^2引脚电平
if (read == 0) delayms(10); //延时10毫秒消热抖动
if (button == 0)
{dn ++; read =button;} //读得P1^2低电平次数累加
if (read ==0 && button ==1) up ++;//弹起次数累加
} //end of while(finish !=1 )
// T0计时一轮结束,进行识别:
TR0 =0;
if (dn >=1 && up ==1 ) //弹起1次,即单击
{ LED1 =0; delayms(1000);} //LED1亮
if (dn >=2 && up ==2 ) //弹起2次,即双击
{ LED2=0; delayms(1000);} //LED2亮
if (dn>=20 && up==0 ) //持续未弹起,即长按
{ LED3=0; delayms(1000);} //LED3亮
} //end of while(1)
} //end of main()
//函数:定时器T0的中断服务 ////////////////
void Time0(void ) interrupt 1 using 1
{
count++; //T0计数溢出中断次数累加
if(count==20) //若T0计数溢出次数累计达设定值
{count =0; finish =1;} //一轮计时结束
TH0=(65536-46083)/256;
TL0=(65536-46083)%256;
} ///////////////////////////////////////
|