找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 757|回复: 4
收起左侧

51单片机识别 "单击.双击.长按" 问题

[复制链接]
ID:143767 发表于 2024-11-21 17:31 | 显示全部楼层 |阅读模式
SCH.jpg
这程序是在本论坛找到的,原设定是按一下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;  
   } ///////////////////////////////////////

回复

使用道具 举报

ID:143767 发表于 2024-11-21 17:32 | 显示全部楼层
我是实际搭的电路试验的
回复

使用道具 举报

ID:123917 发表于 2024-11-21 18:56 | 显示全部楼层
延时时间缩短试试
回复

使用道具 举报

ID:140489 发表于 2024-11-22 08:24 | 显示全部楼层
http://www.51hei.com/bbs/dpj-99528-1.html到这里看看,你会有所收获的
回复

使用道具 举报

ID:401564 发表于 2024-11-22 09:17 | 显示全部楼层
本论坛有现成的状态机,双击和长按都可以,我复制下来用了,没有问题
你应该去学一下状态机,封装成.c文件,可以轻松的套用到其它的单片机上
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表