lingergz 发表于 2014-9-20 15:35:20

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

如题,按下键,进入中断,
    那如何区分 是长按还是短按呢?

haibaogk 发表于 2014-9-20 16:27:06

进入之后计时,根据时间长短判断

黑夜之狼 发表于 2014-9-20 20:17:36

自古真相出二楼

muniao 发表于 2014-9-20 20:32:43

系统要求实时的话,长按处理有的麻烦

th1993 发表于 2014-9-20 21:32:54

同意二楼!

luhuaneda 发表于 2014-9-20 22:47:15

attach://222363.png
引用网上一个按键状态机图,本人觉得有用。在状态6之前增加长按的识别。

fiddly 发表于 2014-9-20 23:06:45

建议定时器中断扫描!

minwang440 发表于 2014-9-21 10:32:11

长按的处理可以参照消抖,短按可以用上升沿或下降沿触发就可以了,

ele-madman 发表于 2014-9-21 10:37:18

定时器中断扫描!

腹黑男 发表于 2014-9-22 11:04:29

他长按短按是处理不同的情况吧所以都用定时器计时好了

lingergz 发表于 2014-9-22 14:43:53

腹黑男 发表于 2014-9-22 11:04
他长按短按是处理不同的情况吧所以都用定时器计时好了

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

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

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

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


      



腹黑男 发表于 2014-9-22 15:25:59

你中断使能关了.....第一次开启了...在触发的时候关闭了定时器开启同时开启中断然后第二次中断之后到执行完while的关闭定时器中间不到20ms...所以在定时器开启中断之前就被关闭了...所以有时候不稳定{:sweat:}之前没用过430不过应该是这样的问题

xiaotaodzgzs 发表于 2014-9-22 15:32:32

进入中断后定时器计数,简单的程序的话也可以试试中断后延时再判断

loveskangaroo 发表于 2014-9-22 15:52:44

定时中断扫描

CrystalShell 发表于 2014-9-22 15:59:49

按下中断,松开中断,测时间就好

Eiman 发表于 2014-9-22 16:01:57

按键处理坛子里面大把,为什么还发帖问啊。

lingergz 发表于 2014-9-22 16:08:57

腹黑男 发表于 2014-9-22 15:25
你中断使能关了.....第一次开启了...在触发的时候关闭了定时器开启同时开启中断然后第二次中断之后到 ...

大侠还能说详细点不?

penguin_boar 发表于 2014-9-22 16:22:13

输入捕获测时间可以吗?

腹黑男 发表于 2014-9-22 16:34:58

lingergz 发表于 2014-9-22 16:08
大侠还能说详细点不?

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

seawind319 发表于 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 < SHORT_KEY_TIME)
                        {
                                KeyDelayTime ++;
                        }
                        else
                        {
                                if (KeyDelayTime < LONG_KEY_TIME)
                                {
                                        KeyDelayTime ++;
                                }
                        }
                }
                else
                {
                        if ((KeyDelayTime > 0) && (KeyDelayTime < LONG_KEY_TIME))
                        {
                                KeyValue = 2 * i + 1;;
                        }
                        else if (KeyDelayTime == LONG_KEY_TIME)
                        {
                                KeyValue = 2 * i + 2;
                        }
                        KeyDelayTime = 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 u8KeyValue;                                 /* 保存读取的键值                        */
LCM_EXT u16 KeyDelayTime;                /* 按键防抖动时间                        */

seawind319 发表于 2014-9-23 11:25:33

seawind319 发表于 2014-9-23 11:24
void ProcKeyScan(void)
{
        u8 i = 0;


希望对你的编程思想有用

lingergz 发表于 2014-9-23 14:46:36

本帖最后由 lingergz 于 2014-9-23 15:27 编辑

seawind319 发表于 2014-9-23 11:25
希望对你的编程思想有用

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

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

lingergz 发表于 2014-9-23 14:49:06

本帖最后由 lingergz 于 2014-9-23 15:25 编辑

腹黑男 发表于 2014-9-22 16:34
你仔细看看你的工作流程啊...就是你中断关闭了没开启的问题


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


#pragma vector=PORT2_VECTOR
__interrupt void PORT2_ISR(void)
{
       
        if(P2IFG & E_BTN)         
        {
          P2IE &= ~E_BTN;         //禁止引脚中断
                P2IFG &= ~ E_BTN;               
       
          pin_flag ++;
          LPM4_EXIT;                   //退出中断
               
          
    }
       
}


void Timer0_init()                //定时器0初始化,上数模式:定时器计数增加至 TACCR0触发中断
{
CCTL0 = CCIE;

TACTL = TASSEL_2 + MC_1;                  // SMCLK, contmode
}


void main(void)
{
   
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
       
    ConfigureClocks();   
    ConfigureSwitches();
        Timer0_init();                              //系统初始化
       
    ConfigureOLED();
   Clear_Screen();
    Write_HZ((unsigned char *)HZ,4,0);
   
    pin_flag = 0;   //全局变量,用于判断上升沿触发,还是下降沿触发
    cnt = 0;         //全局变量,定时器计数器
   
    __bis_SR_register( GIE);   
    LPM4;                                     //开启总中断并进入低功耗模式4
   
    while(1)
    {           
            if(pin_flag==1)                      //下升沿中断,说明是按键开始按下,开启定时器计时
            {
                    CCR0 = 20000;
                    pin_flag=2;                   
                   
            }
            else if(pin_flag==3)                //上升沿中断,证明按键释放。
            {
                    CCR0 = 0;                     //停止定时器,清零判断上升沿和下降沿的标志位
                    pin_flag=0;
                   
                    if(cnt>150)   //long longpress   //开始判断长按和短按
                    {
                            cnt = 0;
                Clear_Screen();
                Write_HZ((unsigned char *)HZ,10,1);
                    }
                    else if(cnt>50)//long press
                    {
                            cnt= 0;
                Clear_Screen();
                Write_HZ((unsigned char *)HZ,5,1);
                    }
            else// short press
            {
            cnt = 0;
            Clear_Screen();
            Write_HZ((unsigned char *)HZ,6,1);
            }
                       
                       
            P2IES |=E_BTN ;    //P2.1 & P2.2 LO/HI edge,按键判断完毕,开启按键下降沿触发
                    P2IE |= E_BTN;
                       
            LPM4;
            }
   
        }
}

gujiamao_love 发表于 2014-9-23 14:49:36

坛子里用状态机的。

lingergz 发表于 2014-9-23 15:26:02

gujiamao_love 发表于 2014-9-23 14:49
坛子里用状态机的。

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

gujiamao_love 发表于 2014-9-23 16:00:32

lingergz 发表于 2014-9-23 15:26
能帮我对照我写的思路 ,看看我的代码问题在哪里不?

你有消抖动吗?

gujiamao_love 发表于 2014-9-23 16:06:14

定时器的多少时间中断一次?

lingergz 发表于 2014-9-23 16:10:33

gujiamao_love 发表于 2014-9-23 16:00
你有消抖动吗?

有啊,


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

gujiamao_love 发表于 2014-9-23 16:17:08

lingergz 发表于 2014-9-23 16:10
有啊,




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

lingergz 发表于 2014-9-23 16:41:59

gujiamao_love 发表于 2014-9-23 16:17
不好意思哈。
你定时器一直开着吗?

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

qqq_147258 发表于 2014-9-23 16:49:27

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

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

gujiamao_love 发表于 2014-9-23 16:52:04

pin_flag 你调试看看这个值对不对

luhuaneda 发表于 2014-9-23 19:44:14

qqq_147258 发表于 2014-9-23 16:49
请问,你有这图的原文链接吗?
正在看状态机,想参考一下。

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

liss 发表于 2014-9-23 20:03:11

状态机。。。以前参考网上例程写过。。。

lingergz 发表于 2014-9-25 20:03:34

gujiamao_love 发表于 2014-9-23 16:52
pin_flag 你调试看看这个值对不对

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


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


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

lingergz 发表于 2014-10-8 13:37:01

mark一下,之前的问题 通过串口打印的方式找到问题了,是按键释放抖动重进中断导致出了问题。
       改成,按键中断程序里改变触发方式——下升沿触发时,开启定时器;下降沿触发时,关闭定时器。
主程序里判断定时时间就好了。

unclewolf 发表于 2014-10-8 13:40:37

定时器扫描就可以了

lingergz 发表于 2014-10-8 13:43:32

unclewolf 发表于 2014-10-8 13:40
定时器扫描就可以了

必须外部中断触发

zhoupy 发表于 2014-10-8 13:57:11

同意二楼,实时要求高的可以按键过程的每个边沿产生一个中断,然后判断中断之间的间隔时间好了

lingergz 发表于 2014-10-8 14:17:09

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

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

sdkw 发表于 2014-10-8 14:42:43

为什么必须中断触发,单片机睡眠吗,如果不睡眠则可以用定时器扫描处理按键

lingergz 发表于 2014-10-8 14:51:16

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

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

sdkw 发表于 2014-10-8 14:57:53

lingergz 发表于 2014-10-8 14:51
低功耗处理,中断唤醒才比较省电啊

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

xuyaqi 发表于 2014-10-8 15:54:33

用边沿触发就行了

lingergz 发表于 2014-10-9 11:12:50

sdkw 发表于 2014-10-8 14:57
如果发生按键中断,则程序可以暂时退出低功耗模式,此时可以判断按键按下的时间,判断是短按还是长按,按 ...

就是这么干的,
页: [1]
查看完整版本: 按键采用管脚触发方式进入中断,如何区分长按、短按