73

帖子

0

TA的资源

一粒金砂(初级)

21
 
一般人手按键动作,从按下到稳定,大概在1mS-10mS之间(根据按键类型不同而不同),稳定期大概在50mS-200mS,当然不算长按。

单片机上一般延时10mS足够去抖(前提是无硬件防抖)。

CE上因为中断响应慢(典型10mS),估计等中断函数开始响应时,抖动已经过去了,所以根据实际情况测试,这部分延时可以考虑很短甚至不用。

针对你的情况,建议你试试这样:
用示波器抓波形,看看一般你快按快放,到底多长时间,多测几次,有个基本值。

在中断响应函数里,什么都不做,即进去就return,这个时间该算是最短的。如果这样还无法满足先降后升的时间,那就不需要考虑延时的问题,而是要考虑目前中断处理里面到底有什么导致了处理慢了。

摸清了这两点,才可有根据的进行下一步。

回复

75

帖子

0

TA的资源

一粒金砂(初级)

22
 
谢谢shuiyan前辈。

我把IST改成什么都不做,果然,就可以双边触发了。无论我怎么按都会产生两次中断。


  1. BOOL
  2. KeybdIstLoop(
  3.     PKEYBD_IST pKeybdIst
  4.     )
  5. {
  6.     SETFNAME(_T("KeybdIstLoop"));

  7.     UINT32  rguiScanCode[16];
  8.     BOOL    rgfKeyUp[16];
  9.     UINT    cEvents;
  10.         // add by wogo at 2009-03-12
  11.         RETAILMSG(1, (TEXT("In KeybdIstLoop Funtion:\r\n")));
  12.     DEBUGCHK(pKeybdIst->hevInterrupt != NULL);
  13.     DEBUGCHK(pKeybdIst->pfnGetKeybdEvent != NULL);
  14.     DEBUGCHK(pKeybdIst->pfnKeybdEvent != NULL);

  15.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

  16. wait_for_keybd_interrupt:
  17.     if (WaitForSingleObject(pKeybdIst->hevInterrupt, INFINITE) == WAIT_OBJECT_0)
  18.     {
  19.                 // add by wogo at 2009-03-12
  20.                 //RETAILMSG(1, (TEXT("Deal with hevInterrupt@@@!!! :\r\n")));
  21.         #if 0
  22.         cEvents = (*pKeybdIst->pfnGetKeybdEvent)
  23.             (pKeybdIst->uiPddId, rguiScanCode, rgfKeyUp);
  24.             
  25.         for (UINT iEvent = 0; iEvent < cEvents; ++iEvent) {
  26.             (*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId,
  27.                 rguiScanCode[iEvent], rgfKeyUp[iEvent]);
  28.         }
  29.         // cEvents could be 0 if this was a partial scan code, like 0xE0
  30.      #endif

  31.         InterruptDone(pKeybdIst->dwSysIntr_Keybd);
  32.                 // add by wogo at 2009-03-12
  33.                 RETAILMSG(1, (TEXT("InterruptDone(pKeybdIst->dwSysIntr_Keybd)@@@!!! :\r\n")));
  34.     }

  35.     goto wait_for_keybd_interrupt;

  36.     ERRORMSG(1, (TEXT("KeybdIstLoop: Keyboard driver thread terminating.\r\n")));
  37.         RETAILMSG(1, (TEXT("KeybdIstLoop: Keyboard driver thread terminating!!! :\r\n")));
  38.     return TRUE;
  39. }
复制代码


不过被屏蔽部分正好是扫描键值的函数,我想想怎么把这个函数尽量减小。

从这个可以看出,这个双边触发的响应速度没有配置成单边触发的快。

 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

23
 
不行啊,我已经把驱动的很多延时都删除了,还是不能响应弹起中断。

咋整的啊。

真是知道原因就是搞不定。
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

24
 
  1.     #if 0
  2.         cEvents = (*pKeybdIst->pfnGetKeybdEvent)(pKeybdIst->uiPddId, rguiScanCode, rgfKeyUp);
  3.             
  4.         for (UINT iEvent = 0; iEvent < cEvents; ++iEvent) {
  5.             (*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId,rguiScanCode[iEvent], rgfKeyUp[iEvent]);
  6.         }
  7.         // cEvents could be 0 if this was a partial scan code, like 0xE0
  8.      #endif
复制代码


怎么这么复杂?键盘芯片不是直接通过I2C读寄存器吗?怎么还需要循环cEvents次?cEvents一般是多少?
for里面的(*pKeybdIst->pfnKeybdEvent)到底执行什么功能?


btw:你怎么用goto来实现WaitForSingleObject的死循环呢?极其少见呀。
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

25
 
  1. 回shuiyan前辈,这个上面的代码不是我写的啊,是微软自带的键盘IST,我只是移植到BSP下编译,这样可以增加打印信息。

  2. 这样写没有问题吧。


  3. (*pKeybdIst->pfnKeybdEvent)是BSP下的代码转换过来的。
  4. 这里有

  5. KEYBD_IST keybdIst;
  6.         keybdIst.hevInterrupt = m_hevInterrupt;
  7.         keybdIst.dwSysIntr_Keybd = dwSysIntr_Keybd;
  8.         keybdIst.uiPddId = v_uiPddId;
  9.         keybdIst.pfnGetKeybdEvent = KeybdPdd_GetEventEx2;
  10.         keybdIst.pfnKeybdEvent = v_pfnKeybdEvent;
  11.                
  12.         KeybdIstLoop(&keybdIst);

  13. KeybdPdd_GetEventEx2是扫面键盘的函数,里面调用了7290驱动,我也纳闷啊,代码没有改,在4.2BSP行,在5.0就不行了。

  14. //主要的扫描码处理函数
  15. static UINT KeybdPdd_GetEventEx2(UINT uiPddId, UINT32 rguiScanCode[16], BOOL rgfKeyUp[16])
  16. {
  17.     SETFNAME(_T("KeybdPdd_GetEventEx2"));

  18.     UINT32   scInProgress = 0;
  19.     static UINT32   scPrevious;

  20.     BOOL            fKeyUp;
  21.     UINT8           ui8ScanCode=0;
  22.     UINT            cEvents = 0;
  23. //        int                                i;

  24.         unsigned char   key[4];

  25.     //DEBUGCHK(rguiScanCode != NULL);
  26.     //DEBUGCHK(rgfKeyUp != NULL);

  27.         //for(i=0;i<4;i++)
  28.         //        key[i] = 0;
  29.         //getsFromKBCTL(&ui8ScanCode, 1);
  30.         ZLG7290_GetKey(key);
  31.        
  32. //        RETAILMSG(1, (_T("zlg7290 get keys: %x %x %x %x \r\n"),key[0],key[1],key[2],key[3]));
  33. //        OEMWriteDebugString((TEXT("zlg7290 get keys!!!!\r\n")));
  34.        
  35. //        RETAILMSG(1, (_T("v_pIICregs->rIICCON : %x\r\n"),v_pIICregs->rIICCON));
  36. //        RETAILMSG(1, (_T("v_pIOPregs->rGPECON : %x\r\n"),v_pIOPregs->rGPECON));

  37.         if(key[0]&0x01) //key down
  38.         {               
  39.                 fKeyUp = FALSE;
  40.                 // enable rising int trigger
  41.                 //v_pIOPregs->rEXTINT1 &= ~(0x7 << 12);   // Clear EINT11
  42.             //v_pIOPregs->rEXTINT1 |= (0x2 << 8);             // fallig edge triggered for EINT11
  43.                 //v_pIOPregs->rEXTINT1 |= (0x6 << 12);                // both edge
  44.                 //v_pIOPregs->rEXTINT1 |= (0x1 << 14);        // enable rising int trigger
  45.         }
  46.         else//key up
  47.         {               
  48.                 fKeyUp = TRUE;
  49.                 // enable falling int trigger
  50.                 //v_pIOPregs->rEXTINT1 &= ~(0x7 << 12);   // Low level  triggered
  51.             //v_pIOPregs->rEXTINT1 |= (0x2 << 8);             // fallig edge triggered for EINT11
  52.                 //v_pIOPregs->rEXTINT1 |= (0x6 << 12);                // both edge
  53.                 //v_pIOPregs->rEXTINT1 |= (0x1 << 13);        //  enable falling int trigger
  54.         }

  55. /*        if( (key[3] & 0x01) == 0)//F1
  56.         {
  57.                 ui8ScanCode = 0x01;                       
  58.         }
  59.         else if( (key[3] & 0x02) == 0)//F2
  60.         {
  61.                 ui8ScanCode        = 0x02;               
  62.         }
  63.         else if( (key[3] & 0x04) == 0)//F3
  64.         {
  65.                 ui8ScanCode        = 0x03;       
  66.         }
  67.         else if( (key[3] & 0x08) == 0)//F4
  68.         {
  69.                 ui8ScanCode = 0x04;                       
  70.         }
  71.         else */
  72.         if(key[1] != 0x0)//other KEYS
  73.         {                       
  74.                 ui8ScanCode = key[1];       
  75.         }
  76.         else
  77.         {
  78.                 ui8ScanCode = 0;
  79.         }
  80.         //sent bl key press event to backlight driver
  81.         /*if(ui8ScanCode == 19) //bl key scancode = 19
  82.         {
  83.                 //only get key down
  84.                 if(fKeyUp == FALSE)
  85.                         SetEvent(evtBLKeyPress);
  86.                 return cEvents;
  87.         }*/ //wsf 20080924
  88.         //v_pIOPregs->rGPFCON |= 0x01;//GPF0 OUTPUT

  89.    // if (fKeyUp==FALSE)                        
  90.    //      v_pIOPregs->rGPFDAT &= ~(1 << 1); /* LED 0 On                 */
  91.    // else
  92.    //     v_pIOPregs->rGPFDAT |=  (1 << 1); /* LED 0 Off                */
  93.        
  94. //    DEBUGMSG(ZONE_SCANCODES,
  95. //        (_T("%s: scan code 0x%08x, code in progress 0x%08x, previous 0x%08x\r\n"),
  96. //       pszFname, ui8ScanCode, scInProgress, scPrevious));

  97.         scInProgress = ui8ScanCode;
  98.         //按键有效,而且键值相同,auto-repeat
  99.     //if ( (scInProgress == scPrevious) && (fKeyUp == FALSE) )
  100.         //{
  101.         //        mdd handles auto-repeat so ignore auto-repeats from keybd
  102.     //}
  103.         //else
  104.         //{
  105.         // Not a repeated key.  This is the real thing.               
  106.                 scPrevious = scInProgress;
  107.                                                                                                       
  108.         rguiScanCode[cEvents] = scInProgress;
  109.                 rgfKeyUp[cEvents] = fKeyUp;
  110.         ++cEvents;
  111.     //}
  112.         //send a user input event to backlight driver!
  113.         SetEvent(evtUserInput);

  114.     return cEvents;
  115. }
复制代码
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

26
 
按键按下只触发一个中断脚,只要通过ZLG7290_GetKey(key);读取寄存器值就行的。
那for (UINT iEvent = 0; iEvent < cEvents; ++iEvent),循环这么多次干吗?
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

27
 

  1. static UINT KeybdPdd_GetEventEx2(UINT uiPddId, UINT32 rguiScanCode[16], BOOL rgfKeyUp[16])
  2. {
  3.     SETFNAME(_T("KeybdPdd_GetEventEx2"));

  4.     UINT32   scInProgress = 0;
  5.     static UINT32   scPrevious;

  6.     BOOL            fKeyUp;
  7.     UINT8           ui8ScanCode;
  8.     UINT            cEvents = 0;

  9.     DEBUGCHK(rguiScanCode != NULL);
  10.     DEBUGCHK(rgfKeyUp != NULL);

  11.         getsFromKBCTL(&ui8ScanCode, 1);

  12.     DEBUGMSG(ZONE_SCANCODES,
  13.         (_T("%s: scan code 0x%08x, code in progress 0x%08x, previous 0x%08x\r\n"),
  14.         pszFname, ui8ScanCode, scInProgress, scPrevious));

  15.     scInProgress = ui8ScanCode;
  16.     if (scInProgress == scPrevious) {
  17.         //        mdd handles auto-repeat so ignore auto-repeats from keybd
  18.     } else {
  19.         // Not a repeated key.  This is the real thing.
  20.         scPrevious = scInProgress;
  21.         
  22.         if (ui8ScanCode & scKeyUpMask) {
  23.             fKeyUp = TRUE;
  24.             scInProgress &= ~scKeyUpMask;
  25.         } else {
  26.             fKeyUp = FALSE;
  27.         }
  28.         
  29.         rguiScanCode[cEvents] = scInProgress;
  30.                 rgfKeyUp[cEvents] = fKeyUp;
  31.         ++cEvents;
  32.     }

  33.     return cEvents;
  34. }
复制代码

——这是没有修改之前的三星自带的键盘扫描函数。cEvents是按下的次数吧。
感觉这样写怪怪的。但是微软也是这么做。
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

28
 
原来的是PS2键盘,使用的中断是下降沿触发的,并没有使用什么双边沿触发,就实现了键盘的功能。估计是弹起的时候也会产生下降沿的。
这个ZLG7290也应该同一个道理吧,想想使用什么办法可以实现。
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

29
 
RETAILMSG(1, (TEXT("cEvents=%d\r\n"), cEvents));
我在里面加入如下打印信息,这个cEvents是等于1的,所以这个不是问题。
真的难以想象,这东西没有多少东西啊。
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

30
 
键盘功能通过偏方实现了功能,但是不能扑捉到键盘弹起中断的问题依然没有解决。

我在按下线程里面加了一个键盘弹起的标志,告诉系统,就这样,这个键盘就搞定了。哈哈
哎,就是加了两行东西。
wait_for_keybd_interrupt:
    if (WaitForSingleObject(pKeybdIst->hevInterrupt, INFINITE) == WAIT_OBJECT_0)
    {
                // add by wogo at 2009-03-12
                //RETAILMSG(1, (TEXT("Deal with hevInterrupt@@@!!! :\r\n")));
        //#if 0
        cEvents = (*pKeybdIst->pfnGetKeybdEvent)
            (pKeybdIst->uiPddId, rguiScanCode, rgfKeyUp);
        //
        //RETAILMSG(1, (TEXT("cEvents=%d\r\n"), cEvents));
        for (UINT iEvent = 0; iEvent < cEvents; ++iEvent) {
        //UINT iEvent = 0
        (*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId, rguiScanCode[iEvent], rgfKeyUp[iEvent]);
        rgfKeyUp[iEvent]=TRUE;——我原来太执着于本身了,不过键盘功能是实现了,但是本质没有解决。
        (*pKeybdIst->pfnKeybdEvent)(pKeybdIst->uiPddId, rguiScanCode[iEvent], rgfKeyUp[iEvent]);
               
        }
        // cEvents could be 0 if this was a partial scan code, like 0xE0
     //#endif

        InterruptDone(pKeybdIst->dwSysIntr_Keybd);
                // add by wogo at 2009-03-12
                //RETAILMSG(1, (TEXT("InterruptDone.Keybd)\r\n")));
    }

感谢各位关照,尤其是shuiyan前辈,他自己忙着加班,还要回我的问题。
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

31
 
那就把这个GetEvent里面用二分法来找最耗时的那个语句(估计是ZLG7290_GetKey(key);),找到后再决定怎么处理。

MAX7349只支持按下触发下降沿中断,释放不触发。MAX7359支持按下、释放都触发下降沿中断。

所以,这个功能是由扫描芯片决定的。
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

32
 
引用 30 楼 shuiyan 的回复:
那就把这个GetEvent里面用二分法来找最耗时的那个语句(估计是ZLG7290_GetKey(key);),找到后再决定怎么处理。

MAX7349只支持按下触发下降沿中断,释放不触发。MAX7359支持按下、释放都触发下降沿中断。

所以,这个功能是由扫描芯片决定的。


以后用MAX7359了,比较安全一点。现在我先不管那么多了,功能实现了,还有别的驱动,音频要搞吧,、
貌似串口还有BUG,搞完这几个估计要搞应用了,现在感觉很汗。什么都不懂。对操作系统了解少之又少。惭愧。
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

33
 
那个贵,一般别指望用。国产也有很多的,或者做maxim兼容的也应该有。

这种解决方法倒特别。以后再解决也可以,只要记得这里有个问题。
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

34
 
我觉得有点奇怪的是在4.2BSP可行,5.0BSP就不行,难道 5.0BSP的效率还要低于4.2?

在ISR中,5.0BSP使用了一些概括性的写法。使用if else
4.2BSP 使用switch,我觉得这个东西效率应该差不多吧。

至今没有搞明白是怎么回事。
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

35
 
随便说一下。你的系统是不是很忙?把IST的线程优先级调高点看看:
SetThreadPriority(GetCurrentThread(), 100);

 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

36
 
引用 34 楼 singlerace 的回复:
随便说一下。你的系统是不是很忙?把IST的线程优先级调高点看看:
SetThreadPriority(GetCurrentThread(), 100);


回singlerace 前辈,没有啊,运行,反应都很快。
我觉得也有可能,有些驱动我没有用到,但是我并没有删除。
我已经把优先级跳到100了,还是不行。

我只能像我上面那样做了。

很多什么PCCARD等驱动我没有去掉,以后去掉看看会怎么样。
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

37
 
IIC时钟是多少?你看看WaitForSingleObject到InterruptDone花了多长时间?
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

38
 
还有,可以用示波器量波形。看中断产生到IIC上有数据延迟是多少,IIC读数据花多长时间,IIC波形好不好,等等。
 
 
 

回复

53

帖子

0

TA的资源

一粒金砂(初级)

39
 
引用 36 楼 singlerace 的回复:
IIC时钟是多少?你看看WaitForSingleObject到InterruptDone花了多长时间?


我把键盘扫描函数屏蔽了,就能产生两次中断了,这个明显是没有扑捉到中断,

现在我这样直接处理效果反而好,不用再次处理中断了。

IIC那个时钟,我现在记不得,明天到公司看看代码才知道。不过我本来在4.2下运行正常的,在IIC相关函数有很多for延时,我现在把它删除了,还是无济于事。
时钟都没有变,把一些延时不要了,还是会这样,所以我只能像上面那样修改IST来巧妙处理。
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

40
 
UP UP 这方面不是很会 写的好!!!!!
 
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表