找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2119|回复: 6
收起左侧

51单片机单按键多击程序修改

[复制链接]
ID:91521 发表于 2020-7-5 09:33 | 显示全部楼层 |阅读模式
本帖最后由 daiya 于 2020-7-5 17:06 编辑

写了一个响应单按键多击的程序,按键弹起大于0.5S后返回键值,有问题,无法运行。可是我才疏学浅,找不到问题出在哪里。请各位高人帮忙看看问题出在哪?

#include <reg52.h>

sbit LED0 = P1^0;
sbit LED1 = P1^1;
sbit LED2 = P1^2;

sbit KEY1 = P3^2;

unsigned int count = 0,ClickFlag = 0,ClickFlagCount = 0,LongClickFlag = 0;
unsigned char i = 0,Click = 0;
unsigned char keynum = 0;

unsigned char keyscan(void)
{
    if(KEY1)
    {                                                
        if(count > 30 && count < 3000)
        {        
                ClickFlag = 1;
                keynum++;
        }
        count = 0;
        if(ClickFlag == 1)
        {               
            if(ClickFlagCount++ > 500)
            {
                ClickFlag = 0;
                ClickFlagCount = 0;
                return keynum;
                keynum = 0;
            }
            else
            {
                ClickFlag = 0;
                ClickFlagCount = 0;
            }        
        }
        else
        {
            ClickFlagCount = 0;
        }
    }   
    else   
    {
        count++;
        if(count > 3000)
            count = 3001;   
    }
    return 0;
}

void main()
{
    EA = 1;       //使能总中断
    TMOD = 0x01;  //设置T0为模式1
    TH0  = 0xFC;  //为T0赋初值0xFC67,定时1ms
    TL0  = 0x67;
    ET0  = 1;     //使能T0中断
    TR0  = 1;     //启动T0

    while (1)
    {
        if(i==1)
            LED0 = ~LED0;
        if(i==2)
            LED1 = ~LED1;
        if(i==3)
            LED2 = ~LED2;
    }     
}

/* 定时器0中断服务函数 */
void InterruptTimer0() interrupt 1
{
    TH0 = 0xFC;  //重新加载初值
    TL0 = 0x67;
    i = keyscan();
}


回复

使用道具 举报

ID:452950 发表于 2020-7-5 12:09 | 显示全部楼层
本帖最后由 xxpp2011 于 2020-7-6 10:13 编辑

while(Key==0)//如果有按键按下
{    count=0;
  while(Key==1)//等待按键弹起
  {
    if(Key==0)//如果按键再次按下
    {
    执行双击操作;
    break;//结束循环
    }
  count++;//计数
  if(count==100)//如果100个周期内无第二次按键则执行单击操作
    {
    执行单击操作;
    break;//结束循环
    }
  }
if(count!=0)break;
}



回复

使用道具 举报

ID:91521 发表于 2020-7-6 08:30 | 显示全部楼层
你给的程序只是双击按键,和我的程序的要求不同
回复

使用道具 举报

ID:401564 发表于 2020-7-6 08:51 | 显示全部楼层
哥们,你另一个帖子已经有几个人帮你了,有C,有汇编,有代码,有算法,有伪代码,就差帮你把所有代码写出来了
单击,双击,长按.短按,这是一个单片机按键应用非常入门的,相对简单的知识
这只是按键问题,用不到定时器的
按键按下之后是一定要去抖动的,可以是5mS的延时,然后,一边延时一边检测按键有没有松开,顺便记录松开的时间,用来判断是长按,短按,还是双击
你还要检测一下超过长按的时间,比如是一直按下那要怎么做...........
回复

使用道具 举报

ID:213173 发表于 2020-7-6 08:51 | 显示全部楼层
按键初次按下开始计时,0.5s后输出键值1~3有效,超过3此按3次计。
  1. #include <reg52.h>

  2. sbit LED0 = P1^0;
  3. sbit LED1 = P1^1;
  4. sbit LED2 = P1^2;

  5. sbit KEY1 = P3^2;

  6. unsigned char  count=0;
  7. bit ClickFlag=0,Click=0;
  8. unsigned char i = 0;
  9. unsigned char keynum = 0;
  10. unsigned int  num;

  11. void keyscan(void)
  12. {
  13.         if(!KEY1)
  14.         {                                                
  15.                 if(++count>10 && ClickFlag==0)
  16.                 {        
  17.                         ClickFlag=1;
  18.                         Click=1;
  19.                         if(keynum<3)
  20.                                 keynum++;
  21.                 }
  22.         }   
  23.         else   
  24.         {
  25.                 count=0;
  26.                 ClickFlag=0;   
  27.         }
  28. }

  29. void main()
  30. {
  31.         TMOD= 0x01;
  32.         TL0 = 0x18;         //1毫秒@12.000MHz
  33.         TH0 = 0xFC;
  34.         TR0 = 1;                 //定时器0开始计时
  35.         ET0 = 1;     //使能T0中断
  36.         EA  = 1;     //使能总中断
  37.         while (1)
  38.         {
  39.                 if(i>0)
  40.                 {
  41.                         if(i==1)
  42.                                 LED0 = ~LED0;
  43.                         if(i==2)
  44.                                 LED1 = ~LED1;
  45.                         if(i>=3)
  46.                                 LED2 = ~LED2;
  47.                         i=0;//清0
  48.                 }
  49.         }     
  50. }

  51. /* 定时器0中断服务函数 */
  52. void InterruptTimer0() interrupt 1
  53. {
  54.         TL0 = 0x18;
  55.         TH0 = 0xFC;
  56.         keyscan();
  57.         if(Click)//开始计时
  58.         {
  59.                 num++;
  60.                 if(num>=500)//0.5s
  61.                 {
  62.                         num=0;   //清0
  63.                         i=keynum;//取键值
  64.                         keynum=0;//键值清0
  65.                         Click=0; //停止计时
  66.                 }
  67.         }
  68. }
复制代码
回复

使用道具 举报

ID:158375 发表于 2020-7-6 09:03 | 显示全部楼层
unsigned char keyscan(void)
只是看到逻辑混乱啊。。。。。。
回复

使用道具 举报

ID:91521 发表于 2020-7-6 11:16 | 显示全部楼层
我添加了注释,不知道可不可以看清楚逻辑了?

unsigned char keyscan(void)
{
    if(KEY1)
    {                                                
        if(count > 30 && count < 3000)    //如果按下时间30ms~3s,认为是单击
        {        
                ClickFlag = 1;    //按键抬起标志置1
                keynum++;    //键号加1
        }
        count = 0;    // 键按下时间计数器清0
        if(ClickFlag == 1)    //如果按键抬起标志为1
        {               
            if(ClickFlagCount++ > 500)    //按键抬起时间大于0.5s
            {
                ClickFlag = 0;    //按键抬起标志清0
                return keynum;    //返回键号
                keynum = 0;    //键号清0
            }
            else    //按键抬起时间小于0.5s
            {
                ClickFlag = 0;
            }        
        }
        else    //如果按键抬起标志为0
        {
            ClickFlagCount = 0;    //清0按键抬起时间计数器
        }
    }   
    else   
    {
        count++;    //按键按下时间计数器加1
        if(count > 3000)    //防止数据溢出
            count = 3001;   
    }
    return 0;
}
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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