Second interrupt dos not work in MSP430

interruptsmsp430

enter image description here

In this project i want to control dc motor with numeric keypad.
when I push a button first time, it works properly but when i push a button second or third times it does not react and it stays button that I pushed first.

Here is the code:

#include "io430.h"
#include "in430.h"

#define ileri BIT0
#define geri BIT1

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;

  DCOCTL=CALDCO_1MHZ;
  BCSCTL1=CALBC1_1MHZ;

  P1OUT = 0x00;
  P1DIR = 0x0F;
  P2OUT  = 0x00;
  P2DIR &= ~BIT0;
  P2IE   = BIT0;
  P2IFG  = 0x00;

  _BIS_SR(GIE);

  for(;;);
}

#pragma vector=PORT2_VECTOR
__interrupt void P2_ISR(void)
{


 if((P1IN && 0xF0) == BIT5+BIT6+BIT7) 
 {P1OUT =BIT0;P2IFG  = 0x00;}

 if(((P1IN && 0xF0)== BIT6+BIT7) && (P1IN && BIT5) == 0)
 {P1OUT =ileri+BIT2;}


P2IFG  = 0x00;

}
when I push a random button and interrupt enable for ex. if(P1IN == BIT5+BIT6+BIT7) =1 and so P1OUT =0X01;. It is okay there is no problem but, if I push another button, second interrupt does not work. Although if((P1IN == BIT6+BIT7) && P1IN!= BIT5) =1 , I cannot make P1OUT= ileri+BIT2.

Could you help me please?

Best Answer

P1IN reads the state of all of P1, not just the pins set to input. Once any of p1.0-3 Are set to logic 1, P1IN will also include those bits. Example:

If P1.5-P1.7 are high, P1IN = 0b11100000
And you set P1.0 high, P1OUT = 0b00000001
Then read P1IN again, P1IN = 0b11100001

So basically you need to mask P1IN when you test it in your if statements.

if ( (P1IN & 0xF0) == BIT5+BIT6+BIT7) {P1OUT =BIT0;}

For example:

P1.1, P1.5, and P1.6 are high, P1IN = 0b01100001
Bitwise And P1IN and 0xF0 aka 0b11110000 to mask the bits you don't want 
you get 0b01100001 & 0b11110000 = 0b01100000 aka 0x60
BIT5 = 0b00100000, BIT6 = 0b01000000, BIT7 = 0b10000000
Added together, that's 0b11100000 aka 0xE0
So you are testing if 0x60 equals 0xE0, which it does not.

Because of that, your second if statement also fails. If P1IN != BIT5, it will be true unless P1IN only equals 0b00100000.

Since the mm74c922 is a simple encoder, outputing 16 known states in binary, on 4 pins, you never need to mess with that type of not equal test, or double tests.

You can test for BIT5+BIT6+BIT7 or BIT6+BIT7, and they will never both be true at the same time, as these are absolute tests.

An easier way, is simply use the bitwise right shift operator >> for the test, and then compare to the actual output of the mm74c922. The >> takes a value and moves it right x number of bits. Any bits that are shifted out are lost, in this case masking them out. In this case, shifting right by 4 means you lose the lower nibble, and the upper nibble becomes the lower nibble.

Remember how BIT5+BIT6+BIT7 =  0b11100000 = 0xE0?
Shifted right by 4, it becomes 0b00001110 aka 0x0E aka 14!
BIT6+BIT7 = 0b11000000 shifted by 4 is 0b1100 aka 0xC aka 12!

if ( (P1IN >> 4) == 14) {P1OUT = BIT0;}
if ( (P1IN >> 4) == 12) {P1OUT = ileri+BIT2;}

Finally, since there are 16 (only 12 used) known states, a switch statement is better than a bunch of if statements.

switch (P1IN >> 4) {
     case 1:
      //do something when var equals 1
      break;
    case 2:
      //do something when var equals 2
      break;
    default: 
      // if nothing else matches, do the default
      // default is optional
}

Here is a good tutorial on bitwise operators http://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101