2012-08-29 34 views
0

我面临着LPC17xx系列外部中断的奇怪问题。恩智浦LPC17xx挂起中断

我有一个外部按钮设置为外部中断1,用下降沿两者的内部作为外部上拉电阻(P2.11):

PinCfg.Funcnum = 1; 
PinCfg.OpenDrain = 0; 
PinCfg.Pinmode = PINSEL_PINMODE_PULLUP; 
PinCfg.Pinnum = 11; 
PinCfg.Portnum = 2; 
PINSEL_ConfigPin(&PinCfg); 
GPIO_SetDir(2,((uint32_t)1<<11),0); 

和:

EXTICfg.EXTI_Line = EXTI_EINT1; 
EXTICfg.EXTI_Mode = EXTI_MODE_EDGE_SENSITIVE; 
EXTICfg.EXTI_polarity = EXTI_POLARITY_LOW_ACTIVE_OR_FALLING_EDGE; 
EXTI_Config(&EXTICfg); 
EXTI_ClearEXTIFlag(EXTI_EINT1); 

和:

NVIC_SetPriority(EINT1_IRQn,1); 
NVIC_EnableIRQ(EINT1_IRQn); 

这是ISR的一部分(包括200毫秒按钮去抖动定时器):

void EINT1_IRQHandler(void) 
{ 
    EXTI_ClearEXTIFlag(1); 

    uint32_t tim1Cnt = LPC_TIM1->TC; 

    if (tim1Cnt > ButtDebounceUs) 
    { 
     LPC_TIM1->TC = 0x00000000; 

     // Do work here 
    } 
} 

“在此工作”部分可能需要一些时间(例如,在某些情况下超过200ms)。这是计划的进一步执行,并且没有问题。

问题是,当ISR首先进入并且我在ISR执行的时候再次按下按钮(这必须快速完成),则挂起的中断被设置,并且如果ISR再次执行第一次结束。这是我猜想的正常行为,因为EXTI_ClearEXTIFlag(1)不会清除NVIC中的任何未决中断。因此,我添加了NVIC_ClearPendingIRQ(EINT1_IRQn)来清除ISR代码中多个位置上的新挂起中断,以确保挂起的中断被清除。奇怪的是,这根本不起作用。

我的一些问题是,我怎样才能通过JTAG /调试器(内存地址?)读取挂起的中断。这里发生了什么?有人可以解释这种行为,也许有线索如何解决它?

谢谢!

+0

这是一个奇怪的外观ISR:有代码,一个声明,然后是更多的代码。你说你添加了一些操作,但不显示它们并要求进行代码审查?在200ms的处理后,不应该重置LPC_TIM1-> TC'。顺便说一句,在ISR中执行200ms的处理通常是一个坏主意。这通常会引起影响,例如在其他地方增加延迟。你应该考虑实现一个tasklet。 – sawdust

+1

你为什么要在isr做这项工作?你需要尽快进出isr。设置一个标志或增加一个计数器,让前台任务看到标志/计数器并处理按钮按下。 –

回答

1

当ISR进入第一和我按第二次[...]

这再次触发EINT1标志,但后您先清除它的按钮。这就是为什么

NVIC_ClearPendingIRQ(EINT1_IRQn)来清除新挂起的中断

不起作用,因为EINT1仍信号中断线路。您需要后“工作”再打电话

EXTI_ClearEXTIFlag(1);

清除这个标志。

0

我知道做这么长的中断程序通常不是一个好主意。但正如我在问题中所说的那样,这是有意的。我需要确保在ISR期间不执行主任务中的其他代码。

但是要回到这个问题:有人指出,将EXTI_ClearEXTIFlag(1)移到ISR的末尾可能是一个好主意。这样,在执行ISR期间不会产生外部中断,也不会设置任何挂起。这有效,但我仍然想知道为什么清除挂起的中断不起作用。也许这只适用于GPIO中断?

相关问题