C - 注册两次后按下按钮 - MSP430



我想创建一个游戏,玩家必须用 MSP430 上的按键重复随机模式的闪烁灯。随机模式是用ADC创建的 - 0表示P1.0闪烁的红灯,1表示P4.7上的绿灯。

自己玩完后,我注意到有时当我按下一个按钮时,它被注册为按下两次。例如:模式为红色/红色/红色/绿色 (0/0/

0/1(,然后按两次左键和右键一次就足够了,因为左按钮的第一次按下被注册为两次按下。
我将游戏代码简化为一个较小的程序,其中只需要重复上面示例的模式:

#include <msp430.h> 
int pattern[4];
unsigned int index = 0;
unsigned int button;
unsigned int buttonPressed = 0;
void Initialize_LED(void)
{
P4DIR = P4DIR | 0x80; 
P4OUT &= ~0x80;
P1DIR = P1DIR | 0x01;   
P1OUT &=~0x01;                                                       
pattern[0] = 0;
pattern[1] = 0;
pattern[2] = 0;
pattern[3] = 1;
}  
void Initialize_Buttons(void){
P1REN |= 0x02;                         
P1OUT |= 0x02;                          
P2REN |= 0x02;                          
P2OUT |= 0x02;                          
P1IFG &= ~0x02;                        
P2IFG &= ~0x02;                         
P1IE |= 0x02;                           
P2IE |= 0x02;                           
//Timer:----------------------------     
TA1CTL = TASSEL_1+ID_0+MC_2+TACLR;  // 
TA1R = 40000;                       // 
// ----------------
_BIS_SR(GIE);                            
}
void main(void)                                                         
{                                                               
WDTCTL = WDTPW + WDTHOLD;                                                                                                             
Initialize_LED();   
Initialize_Buttons();
int done = 0;
while(done == 0){
if(buttonPressed == 1){
if(pattern[index] != button){
P1OUT ^= 0x01;
done++;                       //wrong button --> green light on
} else {
index++;
buttonPressed = 0;
if (index == 4){
done++;
}
} 
}     
}
P1OUT ^= 0x01;                      // correct pattern --> both lights on
P4OUT ^= 0x80;
}

#pragma vector=PORT1_VECTOR // ----------- Interrupt Service Routine -----------
__interrupt void Port1_Interrupt (void) {
buttonPressed = 1;                                      
if (P1IFG&0x02){                          
button = 1;
P1IE &= ~0x02;                          
TA1CTL |= TAIE;                        
TA1R = 50000;                           
}                                         
}
#pragma vector=PORT2_VECTOR // ----------- Interrupt Service Routine -----------
__interrupt void Port2_Interrupt (void) {
buttonPressed = 1;                        
if (P2IFG&0x02){                          
button = 0;
P2IE &= ~0x02;                          
TA1CTL |= TAIE;                         
TA1R = 50000;                           
}                                         
}
#pragma vector=TIMER1_A1_VECTOR             // Timer1_A3 Interrupt Vector(TAIV) handler
__interrupt void TIMER1_A1_ISR(void)
{
switch (__even_in_range(TA1IV, 14))
{
case  0: break;                          
case  2: break;                          
case  4: break;                          
case  6: break;                          
case  8: break;                          
case 10: break;                          
case 12: break;                          
case 14:                                 
P1IFG &= ~0x02;                
P1IE |= 0x02;                  
P2IFG &= ~0x02;                
P2IE |= 0x02;                  
TA1CTL &= ~TAIE;                
break;
default: break;
}  
}

我使用调试器浏览了代码,但找不到这种情况不断发生的原因。有人能帮助我吗?
谢谢你的时间!

每个机械触点都会产生脉冲 - 在打开和关闭期间反弹。您需要为此创建一个去抖过滤器。

我的建议是让您完全避免按钮读取状态的中断。

通过SW对按钮进行去抖动的最佳方法是采样时间长于按钮生成弹跳脉冲(通常约为1-10ms(。

您可以通过每 10 毫秒读取一次按钮的实际状态并将其与以前的状态进行比较来做到这一点。然后,您将拥有完全去抖动的按钮。

我在许多项目中使用这种方法,在这些项目中我不需要硬件滤波器,并且使用相同的原理,例如在任何PC键盘中,无法添加硬件滤波器,因为所有按钮都是多路复用的,但这最好讨论 https://electronics.stackexchange.com

最新更新