Search code examples
cembeddedmicrocontrollerinterruptmsp430

C - button pressed once registered twice - MSP430


I wanted to create a game where a player has to repeat a random pattern of flashing lights with the keys on the MSP430. The random pattern is created with an ADC - 0 represents the red light on P1.0 blinking and 1 the green light on P4.7.

After playing it myself I noticed that sometimes when I press a button once it is registered as pressed twice.

For example: The pattern is red/red/red/green (0/0/0/1) then pressing the left button twice and the right button once is enough because the first push of the left button is registered as two pushes.
I reduced the code of the game to a smaller program in which it's only necessary to repeate the pattern of the example above:

#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;
    }  
}

I went through the code with the debugger but can't find the reason why this keeps happening. Is someone able to help me?
Thanks for your time!


Solution

  • Every mechanical contact generate pulses - bounces during switch ON and also OFF. You need create an debouncing filter for this.

    My proposals is for you to completely avoid interrupts for reading status of buttons.

    Best way to debounce buttons by SW is to sample it with sampling time longer than button generate bounce pulses (it is generally about 1-10ms).

    You can do it by reading actual status of buttons every 10ms and compare it with previous status. Then you will have completely debounced button(s).

    I use this method in many projects, where I don't need HW filter and same principle is used for example in any PC keyboard, where HW filter is not possible to add, because all the buttons are multiplexed, but this is better to discus on https://electronics.stackexchange.com