我们不能再更改客户的电路图,因为硬件已经做好,只要重写驱动。
我们的基本步骤如下:中断是GPIO_37,low active。
首先初始化中断:
//Keyboard IRQ
g_pGPIORegs->GAFR1_L&=~(XLLP_GPIO_AF_BIT_FFDSR_MASK);
g_pGPIORegs->GPDR1 &= ~GPIO_37;
g_pGPIORegs->GFER1 |= GPIO_37;
g_pGPIORegs->GRER1 &= ~GPIO_37
然后在intr.c的enable,disable,done函数中增加中断的设置。
在keypad驱动中,首先为keypad分配地址,如下:
if (g_extKeyPadRegs == NULL)
{
PA.QuadPart = MAINSTONEII_BASE_PA_SECONDARY_FLASH;
g_extKeyPadRegs = (volatile EXT_KEYPAD_REG *) MmMapIoSpace(PA, sizeof(SPDA_KBD_REGS), FALSE);
}
if (g_pGPIORegs == NULL)
{
PA.QuadPart = BULVERDE_BASE_REG_PA_GPIO;
g_pGPIORegs = (volatile BULVERDE_GPIO_REG *) MmMapIoSpace(PA, sizeof(XLLP_GPIO_T), FALSE);
}
if (g_pOSTRegs == NULL)
{
PA.QuadPart = BULVERDE_BASE_REG_PA_OST;
g_pOSTRegs = (volatile BULVERDE_OST_REG *) MmMapIoSpace(PA, sizeof(XLLP_OST_T), FALSE);
}
然后修改KeyPadDataRead函数。
g_pGPIORegs->GRER1 &= ~ GPIO_37; // Disable interrupt
g_pGPIORegs->GFER1 &=~ GPIO_37;
g_pGPIORegs->GEDR1 |= GPIO_37;
//Scan keyboard and read scan code
bRet = (SPDAReadScanCode( (SPDA_KBD_REGS *)g_extKeyPadRegs,pui8Data) == XLLP_TRUE ? TRUE : FALSE);
g_pGPIORegs->GRER1 &= ~GPIO_37; //Enable interrupt
g_pGPIORegs->GFER1 |= GPIO_37;
SPDAReadScanCode是我们自己写的扫描键盘的函数。
现在的问题就是,测试键盘的时候:
1、中断只能发生一次,即我按下一个键一次后,在按其他的键都没有反应了,除非重启动。
2、我按下一个键,在LCD上的显示确是像不停的按,即比方说我按下A键一次,理论上LCD上只显示一个字母a,但是实际上a不停的出现,直到我的wordpad软件崩溃。同时串口信息上显示的是只产生了一次中断,而不是多次。
请大家帮忙分析一下,可能是哪里出现了问题呢?
非常感谢!
27 个解决方案
#1
你的中断线程退出了吗?是否是这个线程一直占用着?
#2
InterruptDone(SYSINTR_KEYPAD);了吗?
#3
对,你的线程退出了吗?
#4
向楼上诸位表示敬意。
OALIntrStaticTranslate(SYSINTR_KEYPAD, IRQ_GPIO0_EXPBD);
这样语句我有。
不过请问中断线程的退出是什么意思?我是个新手,有些东西还不太明白。
在keypad.cpp中,中断的执行过程如下:
调用了KeyPadIsrThread函数,如下:
调用了IsrThreadProc函数,如下:
请帮忙看看,中断线程的退出是如何做的呢?
OALIntrStaticTranslate(SYSINTR_KEYPAD, IRQ_GPIO0_EXPBD);
这样语句我有。
不过请问中断线程的退出是什么意思?我是个新手,有些东西还不太明白。
在keypad.cpp中,中断的执行过程如下:
BOOL KeyPad::IsrThreadStart()
{
HANDLE hthrd;
hthrd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)KeyPadIsrThread,this,0,NULL);
CloseHandle(hthrd);
return TRUE;
}
调用了KeyPadIsrThread函数,如下:
WORD KeyPadIsrThread(KeyPad *v_pKpd)
{
v_pKpd->IsrThreadProc();
return 0;
}
调用了IsrThreadProc函数,如下:
BOOL KeyPad::IsrThreadProc()
{
m_hevInterrupt = CreateEvent(NULL,FALSE,FALSE,NULL);
if (m_hevInterrupt == NULL) {
RETAILMSG(1, (TEXT("IsrThreadProc: InterruptInitialize Failed\r\n")));
}
else
{
if (InterruptInitialize(SYSINTR_KEYPAD, m_hevInterrupt, NULL, 0))
{
KEYBD_IST keyPadIst;
keyPadIst.hevInterrupt = m_hevInterrupt;
keyPadIst.dwSysIntr_Keybd = SYSINTR_KEYPAD;
keyPadIst.uiPddId = v_uiPddId;
keyPadIst.pfnGetKeybdEvent = KeyPadPdd_GetEventEx2;
keyPadIst.pfnKeybdEvent = v_pfnKeyPadEvent;
// Note: no point in trying to set the thread priority here, because KeybdIstLoop()
// forces it after we give up control:
KeybdIstLoop(&keyPadIst);
}
else
{
DEBUGMSG(ZONE_ERROR, (TEXT("KeyPad::IsrThreadProc: InterruptInitialize Failure\r\n")));
}
}
return(0);
}
请帮忙看看,中断线程的退出是如何做的呢?
#5
"我按下一个键,在LCD上的显示确是像不停的按,即比方说我按下A键一次,理论上LCD上只显示一个字母a,但是实际上a不停的出现,直到我的wordpad软件崩溃。同时串口信息上显示的是只产生了一次中断,而不是多次。"
这是因为你打开的是wordpad, 你的驱动只发送了KeyDown的event, 并没有KeyUp的event, 所以会一直打印键值.
所以, 我觉得你的按键弹起时, 中断没有产生, 会不会是在接下中断发生并处理完后你忘记了清中断?
这是因为你打开的是wordpad, 你的驱动只发送了KeyDown的event, 并没有KeyUp的event, 所以会一直打印键值.
所以, 我觉得你的按键弹起时, 中断没有产生, 会不会是在接下中断发生并处理完后你忘记了清中断?
#6
楼主,我觉得是你没有退出线程/清中断——这个中断线程等的代码可以参考BSP下的其他例子。
很容易就发现少了什么了。
很容易就发现少了什么了。
#7
你把SPDAReadScanCode函数贴出来看看
这里面需要处理防抖动,repeat,长按,短按等多种处理情况
再一个你看你的代码跳出这个SPDAReadScanCode函数了吗?而且跳出来后你的上升沿中断也没有重新Enable
这里面需要处理防抖动,repeat,长按,短按等多种处理情况
再一个你看你的代码跳出这个SPDAReadScanCode函数了吗?而且跳出来后你的上升沿中断也没有重新Enable
#8
m_hevInterrupt
this 事件在哪挂起的?
this 事件在哪挂起的?
#9
关注结果.
#10
谢谢大家的帮忙,我的SPDAReadScanCode函数如下,目前还没有做很多判断键值的动作,只做了扫描键盘的动作。请问应该在哪里增加防抖处理呢?谢谢。
XLLP_BOOL_T SPDAReadScanCode( SPDA_KBD_REGS *v_pKeyPadRegs , XLLP_UINT8_T *pui8Data)
{
// total 8*16 key scan_line= bit0-bit3(C) , input_line=bit4-bit7(R)
BYTE tmp_scanLine=0x01;
int i;
XLLP_BOOL_T retval=XLLP_FALSE;
XLLP_UINT32_T C,R,RthBit,c0,c1,c2,c3,c4,c5,c6,c7;
int numOfKeysPressed=0;
XLLP_UINT32_T col[8];
XLLP_UINT32_T temp_indata;
RETAILMSG(1,(TEXT("ReadScanCodeAutomatically-----SPDA\r\n")));
v_pKeyPadRegs->scan_line = 0xFF;
// Scan keyboard
for(i=0;i<8;i++)
{
col[i]=0;
v_pKeyPadRegs->scan_line = ~tmp_scanLine;
temp_indata = v_pKeyPadRegs->data_in;
temp_indata &= 0x00FFFF;
if(temp_indata != 0xFFFF)
{
if(temp_indata != 0xFFFF)
{
col[i] = temp_indata;
numOfKeysPressed +=1;
}
}
tmp_scanLine<<=1;
}
if(numOfKeysPressed == 1)
{
for(i=0;i<8;i++)
{
if(col[i]!=0)
{
C = (XLLP_UINT32_T) i;
R = TransVal(&col[i]);
R <<=4;
}
}
*pui8Data = (unsigned char) (C | R);
}
else
{
if(numOfKeysPressed > 1)
{
c0 = TransVal(&col[0]);
c1 = TransVal(&col[1]);
c2 = TransVal(&col[2]);
c3 = TransVal(&col[3]);
c4 = TransVal(&col[4]);
c5 = TransVal(&col[5]);
c6 = TransVal(&col[6]);
c7 = TransVal(&col[7]);
}
else
*pui8Data = NO_KEY;
}
retval = XLLP_TRUE;
return(retval);
}
int TransVal( XLLP_UINT32_T *val)
{
int i;
for (i=0;i<16;i++)
{
if(!(*val & 0x0001)) return i;
*val >>=1;
}
return i;
}
#11
我的代码已经跳出SPDAReadScanCode函数了,跳出后我enable了中断,如下:
g_pGPIORegs->GRER1 &= ~GPIO_37; //Enable interrupt
g_pGPIORegs->GFER1 |= GPIO_37;
请问这两句是否有问题呢?
#12
谢谢,我也再想这个问题,不过我使用的是下降沿产生中断,除非一直按住键,否则波形就是low一下立刻就被拉高了,这样的话,我如何相应按键弹起的中断呢?
#13
如果线程没有退出,你的打印的东西就不停的执行。
结果很像你的现象。
结果很像你的现象。
#14
谢谢楼上,我是参考MainstroneII的代码修改的keyboard驱动,除了中断和扫描函数外,线程部分都是使用原始的代码。我查看了一下,没有找到线程应该在哪里退出。
#15
关于只能产生一次中断的问题,在串口上我只能看到一次中断信息,同时我测量中断的pin脚,也量不到下降沿产生,请问硬件上量不到中断是否是软件的问题呢?键盘的中断应该是由硬件发出,而软件响应的吧,如果硬件上量不到中断,是否有可能是硬件有问题,或者是肯定硬件有问题?
谢谢了!
谢谢了!
#16
在中断线程处放置打印信息,如果不停的打印,那么就从线程着手吧。
#17
问题解决了一个,在扫描完键盘后没有将扫描的结果清空,造成中断不能继续相应。增加一行:
g_extKeyPadRegs->scan_line = 0x00;
但是按一个key,出现多个字母的问题还没有解决,请大家帮忙看看。
另外,关于键盘的防抖处理,应该是如何做的呢?
谢谢!
g_extKeyPadRegs->scan_line = 0x00;
但是按一个key,出现多个字母的问题还没有解决,请大家帮忙看看。
另外,关于键盘的防抖处理,应该是如何做的呢?
谢谢!
#18
防抖动就是要实现只处理第一次按下的那次,
就是在扑捉到第一次按下的动作之后再次判断是否有按键按下。如果有就让ARM什么都不做,如果没有就说明只按下了一次,可以继续往下运行。
这个原理和单片机的原理是一样的。
#19
非常感谢,我现在发现在builtinkeypad_0409.cpp文件中的BuiltInKeypad_RemapVKey函数在按键中断完成后仍然一直被调用,请问做过pxa270键盘驱动的高人,BuiltInKeypad_RemapVKey这个函数实在哪里被调用的呢?我一直也没有找到。
#20
键盘驱动向系统报告的是按键的压下和抬起动作,可能是没有报告按键的抬起动作引起的。
#21
现在又前进了一步,单次按键已经没有问题了。我们是通过触发两次中断,第一次中断检测key的值,第一次中断结束后,触发第二次中断,检测到0xFF,即NO_KEY,系统收到NO_KEY则表示按键已经弹起。
但是目前的问题是,如果我长按住按键不放一段时间,在松开,系统就无法检测到按键弹起。请问检测按键长按不放的基本方法是什么呢?
请大家帮帮忙,时间紧迫啊,元旦前必须完成。谢谢
但是目前的问题是,如果我长按住按键不放一段时间,在松开,系统就无法检测到按键弹起。请问检测按键长按不放的基本方法是什么呢?
请大家帮帮忙,时间紧迫啊,元旦前必须完成。谢谢
#22
请问按键长击不放的是时候,应该如何处理按键事件呢?现在我们的驱动在按键长击再松开之后,也无法检测中断。
#23
问题解决了,第二次中断的时候,我们原来设置是只检测上升沿,现在设置都检测上升和下降沿,这样长按键的时候,中断也可以持续发出了。谢谢大家的帮忙,帖子过两天再结,看还有没有其他问题。
#24
结贴!
#25
这个是双边缘触发吧,和SD卡类似。
#26
早就告诉你有一个方向的中断在第二次没有重新Enable,而你自己的代码中却注释着Eable interrupt?
g_pGPIORegs->GRER1 &= ~GPIO_37; //Enable interrupt
g_pGPIORegs->GFER1 |= GPIO_37;
#27
唉,看帖子不仔细,花了这么多时间,非常感谢。
结贴。
#1
你的中断线程退出了吗?是否是这个线程一直占用着?
#2
InterruptDone(SYSINTR_KEYPAD);了吗?
#3
对,你的线程退出了吗?
#4
向楼上诸位表示敬意。
OALIntrStaticTranslate(SYSINTR_KEYPAD, IRQ_GPIO0_EXPBD);
这样语句我有。
不过请问中断线程的退出是什么意思?我是个新手,有些东西还不太明白。
在keypad.cpp中,中断的执行过程如下:
调用了KeyPadIsrThread函数,如下:
调用了IsrThreadProc函数,如下:
请帮忙看看,中断线程的退出是如何做的呢?
OALIntrStaticTranslate(SYSINTR_KEYPAD, IRQ_GPIO0_EXPBD);
这样语句我有。
不过请问中断线程的退出是什么意思?我是个新手,有些东西还不太明白。
在keypad.cpp中,中断的执行过程如下:
BOOL KeyPad::IsrThreadStart()
{
HANDLE hthrd;
hthrd = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)KeyPadIsrThread,this,0,NULL);
CloseHandle(hthrd);
return TRUE;
}
调用了KeyPadIsrThread函数,如下:
WORD KeyPadIsrThread(KeyPad *v_pKpd)
{
v_pKpd->IsrThreadProc();
return 0;
}
调用了IsrThreadProc函数,如下:
BOOL KeyPad::IsrThreadProc()
{
m_hevInterrupt = CreateEvent(NULL,FALSE,FALSE,NULL);
if (m_hevInterrupt == NULL) {
RETAILMSG(1, (TEXT("IsrThreadProc: InterruptInitialize Failed\r\n")));
}
else
{
if (InterruptInitialize(SYSINTR_KEYPAD, m_hevInterrupt, NULL, 0))
{
KEYBD_IST keyPadIst;
keyPadIst.hevInterrupt = m_hevInterrupt;
keyPadIst.dwSysIntr_Keybd = SYSINTR_KEYPAD;
keyPadIst.uiPddId = v_uiPddId;
keyPadIst.pfnGetKeybdEvent = KeyPadPdd_GetEventEx2;
keyPadIst.pfnKeybdEvent = v_pfnKeyPadEvent;
// Note: no point in trying to set the thread priority here, because KeybdIstLoop()
// forces it after we give up control:
KeybdIstLoop(&keyPadIst);
}
else
{
DEBUGMSG(ZONE_ERROR, (TEXT("KeyPad::IsrThreadProc: InterruptInitialize Failure\r\n")));
}
}
return(0);
}
请帮忙看看,中断线程的退出是如何做的呢?
#5
"我按下一个键,在LCD上的显示确是像不停的按,即比方说我按下A键一次,理论上LCD上只显示一个字母a,但是实际上a不停的出现,直到我的wordpad软件崩溃。同时串口信息上显示的是只产生了一次中断,而不是多次。"
这是因为你打开的是wordpad, 你的驱动只发送了KeyDown的event, 并没有KeyUp的event, 所以会一直打印键值.
所以, 我觉得你的按键弹起时, 中断没有产生, 会不会是在接下中断发生并处理完后你忘记了清中断?
这是因为你打开的是wordpad, 你的驱动只发送了KeyDown的event, 并没有KeyUp的event, 所以会一直打印键值.
所以, 我觉得你的按键弹起时, 中断没有产生, 会不会是在接下中断发生并处理完后你忘记了清中断?
#6
楼主,我觉得是你没有退出线程/清中断——这个中断线程等的代码可以参考BSP下的其他例子。
很容易就发现少了什么了。
很容易就发现少了什么了。
#7
你把SPDAReadScanCode函数贴出来看看
这里面需要处理防抖动,repeat,长按,短按等多种处理情况
再一个你看你的代码跳出这个SPDAReadScanCode函数了吗?而且跳出来后你的上升沿中断也没有重新Enable
这里面需要处理防抖动,repeat,长按,短按等多种处理情况
再一个你看你的代码跳出这个SPDAReadScanCode函数了吗?而且跳出来后你的上升沿中断也没有重新Enable
#8
m_hevInterrupt
this 事件在哪挂起的?
this 事件在哪挂起的?
#9
关注结果.
#10
谢谢大家的帮忙,我的SPDAReadScanCode函数如下,目前还没有做很多判断键值的动作,只做了扫描键盘的动作。请问应该在哪里增加防抖处理呢?谢谢。
XLLP_BOOL_T SPDAReadScanCode( SPDA_KBD_REGS *v_pKeyPadRegs , XLLP_UINT8_T *pui8Data)
{
// total 8*16 key scan_line= bit0-bit3(C) , input_line=bit4-bit7(R)
BYTE tmp_scanLine=0x01;
int i;
XLLP_BOOL_T retval=XLLP_FALSE;
XLLP_UINT32_T C,R,RthBit,c0,c1,c2,c3,c4,c5,c6,c7;
int numOfKeysPressed=0;
XLLP_UINT32_T col[8];
XLLP_UINT32_T temp_indata;
RETAILMSG(1,(TEXT("ReadScanCodeAutomatically-----SPDA\r\n")));
v_pKeyPadRegs->scan_line = 0xFF;
// Scan keyboard
for(i=0;i<8;i++)
{
col[i]=0;
v_pKeyPadRegs->scan_line = ~tmp_scanLine;
temp_indata = v_pKeyPadRegs->data_in;
temp_indata &= 0x00FFFF;
if(temp_indata != 0xFFFF)
{
if(temp_indata != 0xFFFF)
{
col[i] = temp_indata;
numOfKeysPressed +=1;
}
}
tmp_scanLine<<=1;
}
if(numOfKeysPressed == 1)
{
for(i=0;i<8;i++)
{
if(col[i]!=0)
{
C = (XLLP_UINT32_T) i;
R = TransVal(&col[i]);
R <<=4;
}
}
*pui8Data = (unsigned char) (C | R);
}
else
{
if(numOfKeysPressed > 1)
{
c0 = TransVal(&col[0]);
c1 = TransVal(&col[1]);
c2 = TransVal(&col[2]);
c3 = TransVal(&col[3]);
c4 = TransVal(&col[4]);
c5 = TransVal(&col[5]);
c6 = TransVal(&col[6]);
c7 = TransVal(&col[7]);
}
else
*pui8Data = NO_KEY;
}
retval = XLLP_TRUE;
return(retval);
}
int TransVal( XLLP_UINT32_T *val)
{
int i;
for (i=0;i<16;i++)
{
if(!(*val & 0x0001)) return i;
*val >>=1;
}
return i;
}
#11
我的代码已经跳出SPDAReadScanCode函数了,跳出后我enable了中断,如下:
g_pGPIORegs->GRER1 &= ~GPIO_37; //Enable interrupt
g_pGPIORegs->GFER1 |= GPIO_37;
请问这两句是否有问题呢?
#12
谢谢,我也再想这个问题,不过我使用的是下降沿产生中断,除非一直按住键,否则波形就是low一下立刻就被拉高了,这样的话,我如何相应按键弹起的中断呢?
#13
如果线程没有退出,你的打印的东西就不停的执行。
结果很像你的现象。
结果很像你的现象。
#14
谢谢楼上,我是参考MainstroneII的代码修改的keyboard驱动,除了中断和扫描函数外,线程部分都是使用原始的代码。我查看了一下,没有找到线程应该在哪里退出。
#15
关于只能产生一次中断的问题,在串口上我只能看到一次中断信息,同时我测量中断的pin脚,也量不到下降沿产生,请问硬件上量不到中断是否是软件的问题呢?键盘的中断应该是由硬件发出,而软件响应的吧,如果硬件上量不到中断,是否有可能是硬件有问题,或者是肯定硬件有问题?
谢谢了!
谢谢了!
#16
在中断线程处放置打印信息,如果不停的打印,那么就从线程着手吧。
#17
问题解决了一个,在扫描完键盘后没有将扫描的结果清空,造成中断不能继续相应。增加一行:
g_extKeyPadRegs->scan_line = 0x00;
但是按一个key,出现多个字母的问题还没有解决,请大家帮忙看看。
另外,关于键盘的防抖处理,应该是如何做的呢?
谢谢!
g_extKeyPadRegs->scan_line = 0x00;
但是按一个key,出现多个字母的问题还没有解决,请大家帮忙看看。
另外,关于键盘的防抖处理,应该是如何做的呢?
谢谢!
#18
防抖动就是要实现只处理第一次按下的那次,
就是在扑捉到第一次按下的动作之后再次判断是否有按键按下。如果有就让ARM什么都不做,如果没有就说明只按下了一次,可以继续往下运行。
这个原理和单片机的原理是一样的。
#19
非常感谢,我现在发现在builtinkeypad_0409.cpp文件中的BuiltInKeypad_RemapVKey函数在按键中断完成后仍然一直被调用,请问做过pxa270键盘驱动的高人,BuiltInKeypad_RemapVKey这个函数实在哪里被调用的呢?我一直也没有找到。
#20
键盘驱动向系统报告的是按键的压下和抬起动作,可能是没有报告按键的抬起动作引起的。
#21
现在又前进了一步,单次按键已经没有问题了。我们是通过触发两次中断,第一次中断检测key的值,第一次中断结束后,触发第二次中断,检测到0xFF,即NO_KEY,系统收到NO_KEY则表示按键已经弹起。
但是目前的问题是,如果我长按住按键不放一段时间,在松开,系统就无法检测到按键弹起。请问检测按键长按不放的基本方法是什么呢?
请大家帮帮忙,时间紧迫啊,元旦前必须完成。谢谢
但是目前的问题是,如果我长按住按键不放一段时间,在松开,系统就无法检测到按键弹起。请问检测按键长按不放的基本方法是什么呢?
请大家帮帮忙,时间紧迫啊,元旦前必须完成。谢谢
#22
请问按键长击不放的是时候,应该如何处理按键事件呢?现在我们的驱动在按键长击再松开之后,也无法检测中断。
#23
问题解决了,第二次中断的时候,我们原来设置是只检测上升沿,现在设置都检测上升和下降沿,这样长按键的时候,中断也可以持续发出了。谢谢大家的帮忙,帖子过两天再结,看还有没有其他问题。
#24
结贴!
#25
这个是双边缘触发吧,和SD卡类似。
#26
早就告诉你有一个方向的中断在第二次没有重新Enable,而你自己的代码中却注释着Eable interrupt?
g_pGPIORegs->GRER1 &= ~GPIO_37; //Enable interrupt
g_pGPIORegs->GFER1 |= GPIO_37;
#27
唉,看帖子不仔细,花了这么多时间,非常感谢。
结贴。