Hi all,
Noob question here. I have the example code that turns on an LED when a button is pressed. Now I want to do one action when a button is pressed, and do another action when the button is released. I thought I should just look at P1IES to see if I'm currently looking for a rising or a falling edge, and problem solved. However it doesn't appear to be working.
In the following program I'm trying to toggle one button on when the button is pressed, and the other one on when the button is released. (Of course I could do this by toggling them differently, but I'm trying to understand something more basic here.) However BOTH LEDs turn on when the button is pressed. What am I doing wrong?
int main(void){ WDTCTL = WDTPW + WDTHOLD; P1DIR |= (LED0 + LED1); // Set P1.0 and P1.6 to output direction. P1.3 must stay at input. It has the button on it. P1SEL = 0x0; P1OUT &= ~(LED0 + LED1); // set P1.0 and P1.6 to 0 (LED OFF) P1IE |= BUTTON; // P1.3 interrupt enabled
P1IFG &= ~BUTTON; // P1.3 IFG cleared
__enable_interrupt(); // enable all interrupts for(;;) {}}
// Port 1 interrupt service routine#pragma vector=PORT1_VECTOR__interrupt void Port_1(void){ P1OUT ^= LED0;if (P1IES & BIT3 == 0) { // if the interrupt edge this time was from low to high (so, that corresponding bit is a zero), and it has triggered, then we just pulled the button
P1OUT ^= LED0; } else if (P1IES & BIT3 == BIT3) { // if the interrupt edge this time was from high to low (so, that corresponding bit is a one), and it has triggered, then we just released the button P1OUT ^= LED1; }
P1IFG &= ~BUTTON; // P1.3 IFG cleared P1IES ^= BUTTON; // toggle the interrupt edge. This means that next time this will trigger on the opposite edge to what it triggered on this time
}
David Hutchison1However BOTH LEDs turn on when the button is pressed.
Also, the contents of the P1IES register is undefined after a device register, so it should be initialized before the P1IFG &= ~BUTTON line.
Thanks,
Yep I'm familiar with debounce, but was trying to strip extraneous stuff away to get at the heart of the problem. Even with bouncing I believe this should work, as it's just toggling LED0 whenever it goes from low to high (and doing nothing to LED1), and toggling LED1 whenever it goes from high to low (and doing nothing to LED0). Even with bouncing
I also added P1IES = 0x0; as you recommend. Thanks for that.
However I guess I'm still unsure why the following lines in the interrupt code don't produce the desired results:
if (P1IES & BIT3 == 0) { // if the interrupt edge this time was from low to high (so, that corresponding bit is a zero), and it has triggered, then we just pushed the button P1OUT ^= LED0;} else if (P1IES & BIT3 == BIT3) { // if the interrupt edge this time was from high to low (so, that corresponding bit is a one), and it has triggered, then we just released the button P1OUT ^= LED1;}
Desired result is that on a rising edge, LED0 should toggle, and on a falling edge, LED1 should toggle.
[note that I had an extra P1OUT ^= LED0 in the original code -- this was incorrect but was not the source of the problem]
Thanks for lookin'!
Based upon the I/O pins in use I assume a MSP430 LaunchPad (MSP-EXP430G2) is used. On the LaunchPad pressing the S2 button takes P1.3 low. i.e. a high to low transition means a button press and a low to high transition means a button release. This is the opposite polarity to that expected by the code.
The reason I mentioned the debounce is that a rapid series of edges caused by switch bounce could trigger multiple interrupts which may lead to both leds being turned on.
Hi David,
In the x2xx family user guide, it states that "Writing to P1IES, or P2IES can result in setting the corresponding interrupt flags."
This may explain what your seeing, since the interrupt flag may be triggered twice for the same edge by setting P1ES during your interrupt.
For your purposes, I would suggest using a Timer_A capture on the input pin, which would also have the side-effect of helping with debouncing.
Tony
TonyKaoIn the x2xx family user guide, it states that "Writing to P1IES, or P2IES can result in setting the corresponding interrupt flags."
TonyKaoThis may explain what your seeing, since the interrupt flag may be triggered twice for the same edge by setting P1ES during your interrupt.
a) PxIESx is initialized to 0, so PxIFGx flag is set with a low-to-high transition.
b) A low-to-high transition occurs on the input which triggers one interrupt by setting PxIFGx.
c) While the input remains high PxIESx is changed from 0 to 1, selecting a high-to-low transition, which leaves PxIFGx unchanged.
d) A high-to-low transition occurs on the input which triggers one interrupt by setting PxIFGx.
e) While the input remains low PxIESx is changed from 1 to 0, selecting a low-to-high transition, which leaves PxIFGx unchanged.
f) The sequence repeats from b)
Hi Chester,
Yes you're right, that shouldn't affect PxIFGx in this case.
On further review of the code, I think I know why both LEDs are permanently set.
LED0,1 are initialized to 0.
When the button is first pressed, LED0 is toggled twice since it is from low-to-high. Hence LED0 = 0, LED1 =0.
When the button is released, LED0 is toggled once, and LED1 is toggled once since it is high-to-low. Hence LED0 = 1, LED1 = 1.