搜索
bottom↓
回复: 44

按键采用管脚触发方式进入中断,如何区分长按、短按

[复制链接]

出0入0汤圆

发表于 2014-9-20 15:35:20 | 显示全部楼层 |阅读模式
如题,按下键,进入中断,
    那如何区分 是长按还是短按呢?

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2014-9-20 16:27:06 | 显示全部楼层
进入之后计时,根据时间长短判断

出0入0汤圆

发表于 2014-9-20 20:17:36 | 显示全部楼层
自古真相出二楼

出0入0汤圆

发表于 2014-9-20 20:32:43 | 显示全部楼层
系统要求实时的话,长按处理有的麻烦

出0入0汤圆

发表于 2014-9-20 21:32:54 | 显示全部楼层
同意二楼!

出0入0汤圆

发表于 2014-9-20 22:47:15 | 显示全部楼层
attach://222363.png
引用网上一个按键状态机图,本人觉得有用。在状态6之前增加长按的识别。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-9-20 23:06:45 来自手机 | 显示全部楼层
建议定时器中断扫描!

出0入0汤圆

发表于 2014-9-21 10:32:11 | 显示全部楼层
长按的处理可以参照消抖,短按可以用上升沿或下降沿触发就可以了,

出0入0汤圆

发表于 2014-9-21 10:37:18 | 显示全部楼层
定时器中断扫描!

出0入0汤圆

发表于 2014-9-22 11:04:29 | 显示全部楼层
他长按短按是处理不同的情况吧  所以都用定时器计时好了

出0入0汤圆

 楼主| 发表于 2014-9-22 14:43:53 | 显示全部楼层
腹黑男 发表于 2014-9-22 11:04
他长按短按是处理不同的情况吧  所以都用定时器计时好了

是啊,长按和短按是处理不同情况,按键按下,为低电平。

       目前做法是 首先 设置引脚为  下降沿触发。
     按键中断程序为:关按键中断使能,清标志位,自己设置的全局标志自加一次(标志位初始值为0),并退出低功耗模式。
     定时器设置为:定时器每20ms中断一次,并把时间计数器加1,如果时间计数器大于1——也就是按键按下后40ms,改引脚触发方式为 上升沿触发,并开启引脚中断使能。
      
   主程序里初始化各项后,进入低功耗模式。只能由外部中断唤醒。

   while(1)里   判断全局标志是否等于1,是则启动定时器计时,把全局标志赋值为2。
                    判断全局标志是否为3,是则关闭定时器,清零全局标志。进而根据时间计数器的数值判断
按键是长按 还是 短按。

          但是问题就是好像第一次可以判断,第二次就不行了。或者不稳定,不晓得问题具体在哪。


      



出0入0汤圆

发表于 2014-9-22 15:25:59 | 显示全部楼层
你中断使能关了.....第一次开启了...在触发的时候关闭了  定时器开启  同时开启中断  然后第二次中断之后到执行完while的关闭定时器中间不到20ms...所以在定时器开启中断之前就被关闭了...所以有时候不稳定  之前没用过430  不过应该是这样的问题

出0入4汤圆

发表于 2014-9-22 15:32:32 | 显示全部楼层
进入中断后定时器计数,简单的程序的话也可以试试中断后延时再判断

出0入0汤圆

发表于 2014-9-22 15:52:44 来自手机 | 显示全部楼层
定时中断扫描

出0入0汤圆

发表于 2014-9-22 15:59:49 | 显示全部楼层
按下中断,松开中断,测时间就好

出0入0汤圆

发表于 2014-9-22 16:01:57 | 显示全部楼层
按键处理坛子里面大把,为什么还发帖问啊。

出0入0汤圆

 楼主| 发表于 2014-9-22 16:08:57 | 显示全部楼层
腹黑男 发表于 2014-9-22 15:25
你中断使能关了.....第一次开启了...在触发的时候关闭了  定时器开启  同时开启中断  然后第二次中断之后到 ...

大侠还能说详细点不?

出0入0汤圆

发表于 2014-9-22 16:22:13 | 显示全部楼层
输入捕获测时间可以吗?

出0入0汤圆

发表于 2014-9-22 16:34:58 | 显示全部楼层
lingergz 发表于 2014-9-22 16:08
大侠还能说详细点不?

你仔细看看你的工作流程啊...就是你中断关闭了没开启的问题

出0入0汤圆

发表于 2014-9-23 11:24:57 | 显示全部楼层
void ProcKeyScan(void)
{
        u8 i = 0;
       
        for (i = 0; i < KEY_ITEM; i++)
        {
                if ((P6IN &(0x04 << i)) == 0)
                {
                        if (KeyDelayTime[i] < SHORT_KEY_TIME)
                        {
                                KeyDelayTime[i] ++;
                        }
                        else
                        {
                                if (KeyDelayTime[i] < LONG_KEY_TIME)
                                {
                                        KeyDelayTime[i] ++;
                                }
                        }
                }
                else
                {
                        if ((KeyDelayTime[i] > 0) && (KeyDelayTime[i] < LONG_KEY_TIME))
                        {
                                KeyValue = 2 * i + 1;;
                        }
                        else if (KeyDelayTime[i] == LONG_KEY_TIME)
                        {
                                KeyValue = 2 * i + 2;
                        }
                        KeyDelayTime[i] = 0;
                }
        }
}
/* 看门狗定时器B0 溢出中断(32ms)*/
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
        ProcKeyScan();                // 处理按键扫描
}

#define SHORT_KEY_TIME                2                        /* 短按时间为: 32ms ×2 = 64ms        */
#define LONG_KEY_TIME                70                        /* 长按时间为: 32ms ×70= 2.1s        */

LCM_EXT u8  KeyValue;                                 /* 保存读取的键值                        */
LCM_EXT u16 KeyDelayTime[KEY_ITEM];                /* 按键防抖动时间                        */

出0入0汤圆

发表于 2014-9-23 11:25:33 | 显示全部楼层
seawind319 发表于 2014-9-23 11:24
void ProcKeyScan(void)
{
        u8 i = 0;

希望对你的编程思想有用

出0入0汤圆

 楼主| 发表于 2014-9-23 14:46:36 | 显示全部楼层
本帖最后由 lingergz 于 2014-9-23 15:27 编辑
seawind319 发表于 2014-9-23 11:25
希望对你的编程思想有用


非常感谢,虽然不符合我的低功耗模式要求。

我这个按键必须由 中断触发

出0入0汤圆

 楼主| 发表于 2014-9-23 14:49:06 | 显示全部楼层
本帖最后由 lingergz 于 2014-9-23 15:25 编辑
腹黑男 发表于 2014-9-22 16:34
你仔细看看你的工作流程啊...就是你中断关闭了没开启的问题


  1. #pragma vector=TIMER0_A0_VECTOR
  2. __interrupt void Timer_A (void)
  3. {
  4.         cnt++;
  5.         if(cnt>1)                  //按键按下后40ms,改变引脚为 上升沿触发,从而避免抖动                        
  6.         {
  7.             P2IES &= ~ E_BTN ;    //P2.1 & P2.2 LO/HI edge
  8.                
  9.                 P2IE |= E_BTN;       //开启引脚中断
  10.                
  11.         }
  12. }


  13. #pragma vector=PORT2_VECTOR
  14. __interrupt void PORT2_ISR(void)
  15. {
  16.        
  17.         if(P2IFG & E_BTN)         
  18.         {
  19.             P2IE &= ~E_BTN;           //禁止引脚中断
  20.                 P2IFG &= ~ E_BTN;               
  21.        
  22.             pin_flag ++;
  23.             LPM4_EXIT;                   //退出中断
  24.                
  25.             
  26.     }
  27.        
  28. }


  29. void Timer0_init()                //定时器0初始化,上数模式:定时器计数增加至 TACCR0触发中断
  30. {
  31.   CCTL0 = CCIE;
  32.   
  33.   TACTL = TASSEL_2 + MC_1;                  // SMCLK, contmode
  34. }


  35. void main(void)
  36. {
  37.    
  38.     WDTCTL = WDTPW + WDTHOLD; // Stop WDT
  39.        
  40.     ConfigureClocks();   
  41.     ConfigureSwitches();
  42.         Timer0_init();                                //系统初始化
  43.        
  44.     ConfigureOLED();
  45.      Clear_Screen();
  46.     Write_HZ((unsigned char *)HZ,4,0);
  47.    
  48.     pin_flag = 0;     //全局变量,用于判断上升沿触发,还是下降沿触发
  49.     cnt = 0;           //全局变量,定时器计数器
  50.    
  51.     __bis_SR_register( GIE);   
  52.     LPM4;                                     //开启总中断并进入低功耗模式4
  53.    
  54.     while(1)
  55.     {           
  56.             if(pin_flag==1)                      //下升沿中断,说明是按键开始按下,开启定时器计时
  57.             {
  58.                     CCR0 = 20000;
  59.                     pin_flag=2;                   
  60.                    
  61.             }
  62.             else if(pin_flag==3)                //上升沿中断,证明按键释放。
  63.             {
  64.                     CCR0 = 0;                       //停止定时器,清零判断上升沿和下降沿的标志位
  65.                     pin_flag=0;
  66.                    
  67.                     if(cnt>150)   //long longpress   //开始判断长按和短按
  68.                     {
  69.                             cnt = 0;
  70.                 Clear_Screen();
  71.                 Write_HZ((unsigned char *)HZ,10,1);
  72.                     }
  73.                     else if(cnt>50)//long press
  74.                     {
  75.                             cnt= 0;
  76.                 Clear_Screen();
  77.                 Write_HZ((unsigned char *)HZ,5,1);
  78.                     }
  79.             else  // short press
  80.             {
  81.               cnt = 0;
  82.               Clear_Screen();
  83.               Write_HZ((unsigned char *)HZ,6,1);
  84.             }
  85.                        
  86.                        
  87.             P2IES |=  E_BTN ;    //P2.1 & P2.2 LO/HI edge,按键判断完毕,开启按键下降沿触发
  88.                     P2IE |= E_BTN;
  89.                        
  90.             LPM4;
  91.             }
  92.    
  93.         }
  94. }
复制代码

出0入0汤圆

发表于 2014-9-23 14:49:36 | 显示全部楼层
坛子里用状态机的。

出0入0汤圆

 楼主| 发表于 2014-9-23 15:26:02 | 显示全部楼层
gujiamao_love 发表于 2014-9-23 14:49
坛子里用状态机的。

能帮我对照我写的思路 ,看看我的代码问题在哪里不?

出0入0汤圆

发表于 2014-9-23 16:00:32 | 显示全部楼层
lingergz 发表于 2014-9-23 15:26
能帮我对照我写的思路 ,看看我的代码问题在哪里不?

你有消抖动吗?

出0入0汤圆

发表于 2014-9-23 16:06:14 | 显示全部楼层
定时器的多少时间中断一次?

出0入0汤圆

 楼主| 发表于 2014-9-23 16:10:33 | 显示全部楼层

有啊,


   我是用定时器计数方式消除抖动的。

出0入0汤圆

发表于 2014-9-23 16:17:08 | 显示全部楼层

不好意思哈。
你定时器一直开着吗?

出0入0汤圆

 楼主| 发表于 2014-9-23 16:41:59 | 显示全部楼层
gujiamao_love 发表于 2014-9-23 16:17
不好意思哈。
你定时器一直开着吗?

没啊, 不晓得你用没用过 MSP430的定时器,
     往TACRR0 写入0,就可以停止定时器了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-9-23 16:49:27 | 显示全部楼层
luhuaneda 发表于 2014-9-20 22:47
attach://222363.png
引用网上一个按键状态机图,本人觉得有用。在状态6之前增加长按的识别。 ...

请问,你有这图的原文链接吗?
正在看状态机,想参考一下。

出0入0汤圆

发表于 2014-9-23 16:52:04 | 显示全部楼层
pin_flag 你调试看看这个值对不对

出0入0汤圆

发表于 2014-9-23 19:44:14 | 显示全部楼层
qqq_147258 发表于 2014-9-23 16:49
请问,你有这图的原文链接吗?
正在看状态机,想参考一下。

http://www.mathertel.de/Arduino/OneButtonLibrary.aspx

出0入0汤圆

发表于 2014-9-23 20:03:11 | 显示全部楼层
状态机。。。以前参考网上例程写过。。。

出0入0汤圆

 楼主| 发表于 2014-9-25 20:03:34 | 显示全部楼层
gujiamao_love 发表于 2014-9-23 16:52
pin_flag 你调试看看这个值对不对

我看了下,这个变量值 没问题。


现在来看 定时器的开启  和  关闭出了问题,..


谁有用过MSP430g2533 的定时器0 开启 和 关闭?

出0入0汤圆

 楼主| 发表于 2014-10-8 13:37:01 | 显示全部楼层
mark一下,之前的问题 通过串口打印的方式找到问题了,是按键释放抖动重进中断导致出了问题。
       改成,按键中断程序里改变触发方式——下升沿触发时,开启定时器;下降沿触发时,关闭定时器。
主程序里判断定时时间就好了。

出0入0汤圆

发表于 2014-10-8 13:40:37 | 显示全部楼层
定时器扫描就可以了

出0入0汤圆

 楼主| 发表于 2014-10-8 13:43:32 | 显示全部楼层
unclewolf 发表于 2014-10-8 13:40
定时器扫描就可以了

必须外部中断触发

出0入4汤圆

发表于 2014-10-8 13:57:11 | 显示全部楼层
同意二楼,实时要求高的可以按键过程的每个边沿产生一个中断,然后判断中断之间的间隔时间好了

出0入0汤圆

 楼主| 发表于 2014-10-8 14:17:09 | 显示全部楼层
zhoupy 发表于 2014-10-8 13:57
同意二楼,实时要求高的可以按键过程的每个边沿产生一个中断,然后判断中断之间的间隔时间好了 ...

最后我就是这么干的,坛子里大牛好多!

出0入0汤圆

发表于 2014-10-8 14:42:43 | 显示全部楼层
为什么必须中断触发,单片机睡眠吗,如果不睡眠则可以用定时器扫描处理按键

出0入0汤圆

 楼主| 发表于 2014-10-8 14:51:16 | 显示全部楼层
sdkw 发表于 2014-10-8 14:42
为什么必须中断触发,单片机睡眠吗,如果不睡眠则可以用定时器扫描处理按键 ...

低功耗处理,中断唤醒才比较省电啊

出0入0汤圆

发表于 2014-10-8 14:57:53 | 显示全部楼层
lingergz 发表于 2014-10-8 14:51
低功耗处理,中断唤醒才比较省电啊

如果发生按键中断,则程序可以暂时退出低功耗模式,此时可以判断按键按下的时间,判断是短按还是长按,按键处理完成后再进入低功耗

出0入0汤圆

发表于 2014-10-8 15:54:33 | 显示全部楼层
用边沿触发就行了

出0入0汤圆

 楼主| 发表于 2014-10-9 11:12:50 | 显示全部楼层
sdkw 发表于 2014-10-8 14:57
如果发生按键中断,则程序可以暂时退出低功耗模式,此时可以判断按键按下的时间,判断是短按还是长按,按 ...

就是这么干的,
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 23:15

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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