- MSP430-ez430 Basics - reading in pushbutton values
- Posted by Hamza on April 21st, 2008
Hi all,
I just received my ez430 and the extra modules (with MSP430F2012) and
I am just trying to get my head round some basic stuff, like reading
in a port value to detect pushbuttons etc. I must say I am not very
experienced so please be gentle 
I've connected two pushbuttons, one to P1.3 and one to P1.4 and they
are pulled up to Vcc with 10K resistors. I've hooked them up to my
multimeter and they drop to 0V when the button is pressed so they seem
to be working.
I've also coded this little bit of software, using mspgcc and I can't
seem to get it to work. I know the LEDs are working as I've done a
little blinking lights sequence with them but the following bit of
code doesn't seem to 'register' when I press the push buttons.
#include <io.h>
#include <signal.h>
#ifndef __MSP430_2012__
#define __MSP430_2012__
#endif
int main(void){
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR = 0x1D;
P1OUT = 0x00;
for (;
{
if ( !(P1IN & 0x10) ){ // button a on port1.3 pressed?
P1OUT |= 0x80; // turn on led 1 (port 1.0)
} else if ( !(P1IN & 0x08) ){ // button b on port1.4
pressed?
P1OUT |= 0x20; // turn on led 2 (port 1.2)
} else {
P1OUT = 0xFF;
}
}
}
I would appreciate any pointers as it just doesn't seem to work 
Thanks!
Hamza.
- Posted by larwe on April 21st, 2008
Hi,
On Apr 21, 1:33*pm, Hamza <hamzasag...@googlemail.com> wrote:
First, thank you for posting such a well-enunciated inquiry. It
doesn't happen often enough here.
As a rule you should also make it a point to initialize the PxSEL
register when using the MSP430 family. So add P1SEL = 0x00 here. But
that isn't your problem:
No it isn't, this code checks if P1.4 is pressed.
No it isn't... this code turns on P1.7.
No it isn't... this code checks if P1.3 is pressed.
No it isn't... this code turns on P1.5
and this code ensures that both LEDs are always on even if the buttons
aren't pressed 
The header files define macros for you to access the bits directly to
avoid confusion.
So try this:
if ( !(P1IN & BIT3) ){ // button a on port1.3
pressed?
P1OUT |= BIT0; // turn on led 1 (port 1.0)
} else if ( !(P1IN & BIT4) ){ // button b on port1.4
pressed?
P1OUT |= BIT2; // turn on led 2 (port 1.2)
} else {
P1OUT &= ~(BIT0 | BIT2); // turn off LEDs
}
This code is still not bug-free (consider what happens when only one
button is pressed, then the second is pressed and released while the
first is still held down), but it is closer to what you're trying to
do.
- Posted by Hamza on April 21st, 2008
On Apr 21, 8:00 pm, larwe <zwsdot...@gmail.com> wrote:
Silly me!
I really should have looked deeper before I let it out, sorry about
the mess 
Thank you very much for your help, and also the hint on the shorthand
BIT macros. I understand the flaws of this approach to handling
pushbuttons, I was just trying to test if I was actually reading
anything.
Moving one step ahead on the same topic, I have written this little
bit of code to implement interrupt handling, which I believe is a
better alternative to polling. The idea is the LED on P1.0 will toggle
away happily until a key is pressed and then the interrupt handler
p1_interrupt() will kick in and toggle the LED on P1.2.
I have scavenged bits and pieces from some samples and came up with
the following mess:
#include <io.h>
#include <signal.h>
#ifndef __MSP430_2012__
#define __MSP430_2012__
#endif
interrupt (PORT1_VECTOR) p1_interrupt(){
dint();
if(P1IFG==0x01){
P1OUT ^= BIT2; // toggle LED on P1.2
}
eint();
}
int main(void){
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR = 0x07;
P1OUT = 0x00;
P1SEL = 0x00;
P1IFG = 0X00; // No interrupt is pending
P1IES = 0X01; // The PxIFGx flag is set with a high-to-low transition
P1IE = 0X01; // The interrupt is enabled
eint();
int i;
for (;
{
// toggle the LED on p1.0
P1OUT ^= BIT0;
i = 20000;
while (i != 0){ i--; };
}
}
It compiles fine but the problem is the program never leaves the
interrupt handler! P1.2 toggles continuously whether I press the
button or not.
Am I missing something really obvious again?
Many thanks,
Hamza.
- Posted by larwe on April 21st, 2008
On Apr 21, 7:25*pm, Hamza <hamzasag...@googlemail.com> wrote:
Why are you doing this, by the way? You shouldn't need to define any
chip-specific macros. Set the chip type in the compiler settings.
Otherwise the compiler is pulling in the wrong ioxxxxxx.h file.
You are not clearing the interrupt request flag here, so as soon as
the ISR exits, the interrupt fires again. Some interrupts
automatically clear their appropriate request flag when the handler is
called - without looking at the datasheet I don't know if the pin-
change interrupt is one of these - I guess not, from your description
of the behavior.
By the way, your code here is going to be toggling P1.0 constantly,
and toggling P1.2 when you press the button. HOWEVER, it probably
isn't going to work very well because you haven't put any debouncing
in there. You'll probably see P1.2 toggle several times when you press
or release the button.
- Posted by Hamza on April 22nd, 2008
On Apr 22, 12:36 am, larwe <zwsdot...@gmail.com> wrote:
I altered the makefile and it looks much cleaner without all this now,
I don't know why I didn't do this before 
Absolutely spot on. P1IFG = 0x00; solved everything, Thanks!
Strangely enough I didn't get any debouncing issues, but just to be on
the safe side I've added it in.
This seems to be working for me so I'm just throwing this in for
further google searches 
if(P1IFG & BIT3){
d = 500;
while(d){ d--; }
if(P1IN & BIT3){
P1OUT ^= BIT2;
}
}
Many thanks for your help larwe, it's much appreciated.
Cheers,
Hamza.