0
\$\begingroup\$

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?

\$\endgroup\$
11
  • \$\begingroup\$ Are you clearing the interrupt flag from the first button in your ISR? \$\endgroup\$ Commented Dec 16, 2014 at 20:13
  • \$\begingroup\$ @SomeHardwareGuy looks like this line does P2IFG = 0x00; \$\endgroup\$
    – Eugene Sh.
    Commented Dec 16, 2014 at 20:36
  • \$\begingroup\$ Is P2IE = BIT0; only enabling a single input bit to be an active interrupt. In other words is your mask set correctly? \$\endgroup\$ Commented Dec 16, 2014 at 20:43
  • \$\begingroup\$ He has a single interrupt on p2.0, which then polls the state of p1 pound 4-7. \$\endgroup\$
    – Passerby
    Commented Dec 16, 2014 at 20:48
  • \$\begingroup\$ Yeah I see that now, trying to do too much at once... \$\endgroup\$ Commented Dec 16, 2014 at 20:54

1 Answer 1

2
\$\begingroup\$

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

\$\endgroup\$
4
  • \$\begingroup\$ I changed like this. When I debug step by step diagram is ok. it checks all if statements and go back for(;;) but, it skip if inside. what i am saying is that it check an if statement but although this if statement is true, it does not P1OUT=BIT1. @Passerby \$\endgroup\$ Commented Dec 16, 2014 at 22:10
  • \$\begingroup\$ if((P1IN && 0xF0) == BIT5+BIT6+BIT7) {P1OUT =BIT0;P2IFG = 0x00;} if(((P1IN && 0xF0)== BIT6+BIT7) && (P1IN && BIT5) == 0) {P1OUT =ileri+BIT2;} \$\endgroup\$ Commented Dec 16, 2014 at 22:10
  • \$\begingroup\$ @AliAKÇAKMAK fixed and updated. \$\endgroup\$
    – Passerby
    Commented Dec 17, 2014 at 1:54
  • \$\begingroup\$ Thank you very much it works. I really appreciate . This info is really usefull for me. \$\endgroup\$ Commented Dec 17, 2014 at 17:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.