Jump to content
43oh

Detecting interrupt edge


Recommended Posts

Hello All,

 

I have been playing with my new launch pad trying to figure things out. I am currently attempting to use a single button for multiple purposes. For instance, if the button is held for 3 sec the red led is lit, but if the button is pressed and released before 3 sec, the green one is lit. I thought that this would be a simple exercise, but I haven't been able to quite get it to work.

 

I know that I can toggle the interrupt edge using P1IES ^= BUTTON (Where BUTTON = BIT3), but what I don't know is how to determine if the edge is high or low. I have been looking through code and searching on line, but I must have missed it somewhere. If anyone has any ideas (hey, I'll even take leads if you think I ought to "work for it" more) ;) .

 

Thanks

j.a.n.

Link to post
Share on other sites

Alternatively, you can tie 2 pins together and get triggers on both edges. You can also do something more fancy and use timer's capture function. You will get triggers on both edges and you will get timing.

 

EDIT: I just realized what you are trying to do and that is a neat idea. I have a problem with getting my encoder switch to work properly so I will try using your approach.

Link to post
Share on other sites

Thanks gordon! I think that is what I am looking for, I'll give that a try and see how it works. I am basically trying to have one LED light if the button has been held for a certain period (3 sec) and the other to be lit if the button has been released before that time. Kind of like the mode button common to digital watches; if you press the button it shows the date, but if you hold the button, it allows you to edit the time.

 

j.a.n.

Link to post
Share on other sites

Sometimes you don't need traditional debouncing depending on how fast a response time you require.

 

I've used interrupt timed polling of a switch input. That is, continuously check the state of the switch input every 20ms. If it is active four or eight times in a row then it's considered a valid input signal.

 

It slows down the response time but it frees you to do other things in the mean time.

Link to post
Share on other sites

I believe the code will go something like this

 

Wait for button press, --> when pressed start interrupt

 

ISR --> start timer, and change edge select, exit ISR --> wait for new interrupt

 

when button is released --> ISR should stop - stop timer--> if timer is less then 3 seconds display option 1

 

if longer then 3 secs --> option 2

 

 

you will need to De bounce the switch otherwise this setup may not work

 

 

for edge select

P1ES = 1 == High to low

P1ES = 0 == low to high

 

be mindful of how you set your pull up and pull down on that port

 

to determine your edge, you need to know the starting state,

if its a button tied to ground - you would us a pull up resister and it would be considered High state -- when pressed it would go low

and if its a button tied to a voltage(3.3V) then you would use a pulldown and the starting state would be low, and when the button is pressed the pin goes High

 

 

you can also find the initial state by changing the pin to an input and reading the value (1|0)

Link to post
Share on other sites
Sometimes you don't need traditional debouncing depending on how fast a response time you require.

 

The problem in this case is that that when the switch is depressed, it is likely to generate several interrupts before settling into the full-on state. This is going to need to be accounted for in the program logic if a hardware de-bounce circuit is not used.

Link to post
Share on other sites

Thanks everyone for the great responses.

 

jsolarski - That is just about what my thought process was on the matter. It was good to have confirmation that I was thinking along a working path.

 

I managed to get the code to work. I tried the different suggestions posted. Using (P1IES & BIT3) != 0 always returned as true and using P1ES just threw errors. I am guessing it is because I missed something and that these techniques would work with more nimble fingers at the keyboard.

 

My solution was to create a variable to indicate when the button was pressed, and a variable to indicate when the timer was set. I'll include the code below. I invite you all to make suggestions on how to make the code leaner, more efficient, etc. My goal is to learn how to make this code efficient, so that I can store it a a bag of tricks for when I start doing things that are more complex. For now however, I am just trying to learn how all of this works.

 

 

#include 

#define LED_RED BIT0
#define LED_GR BIT6
#define BUTTON BIT3

int pressed = 0;// declare variable to indicate button press
int myTimer = 0;// declare variable to indicate timer running
int main(void)
{
   WDTCTL = WDTPW + WDTHOLD;// Stop watchdog timer
   P1DIR |= (LED_RED + LED_GR);// Set P1.0 to output direction
   P1OUT &= ~(LED_RED + LED_GR);// set P1.0 to 0 (LEDs 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)
{
   if (pressed == 0)// If the button hasn't been pressed yet
   {
       TACTL = TASSEL0 + ID_3 + TACLR;// TACLK, divider 8, clear TAR,
       TACCTL0 = CCIE;// enable interrupt
       TACCR0 = 4000;// set timer for  3 seconds
       TACTL |= MC_1;// setting mode bits starts timer up mode
       myTimer = 1;// set this to 1 to indicate the timer has started
       pressed = 1;// set this to 1 to indicate the button has been pressed
   } // end If pressed
   else if ((pressed == 1))//If the button has been pressed
   {
       pressed = 0;// reset button press variable
       if (myTimer == 1)// If the timer is going, this means that 3 sec hasn't elapsed or this is a button release
       {
           P1OUT ^= (LED_GR);// P1.0 = toggle
           TACCTL0 ^= CCIE;// turn off timer interupt
           TACTL = MC_0 + TACLR;// stop timer and clear timer
           myTimer = 0;
       }
   }
   P1IFG &= ~BUTTON;// P1.3 IFG cleared
   P1IES ^= BUTTON;// toggle the interrupt edge,
// This means that an interrupt will be triggered
// on p1.3 button up as well as button press
} //end PORT1_VECTOR

// Timer interrupt
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0(void)
{
   TACCTL0 ^= CCIE;// enable interrupt
   TACTL = MC_0 + TACLR;// stop timer and clear timer
   P1OUT ^= (LED_RED);// P1.0 = toggle
   P1IFG &= ~BUTTON;// P1.3 IFG cleared
   myTimer = 0;  // set my timer to 0 since the time (3 sec) has elapsed

} //end TIMERA0_VECTOR

Link to post
Share on other sites
Sometimes you don't need traditional debouncing depending on how fast a response time you require.

 

The problem in this case is that that when the switch is depressed, it is likely to generate several interrupts before settling into the full-on state. This is going to need to be accounted for in the program logic if a hardware de-bounce circuit is not used.

But I don't trigger an ISR when the button is pressed. Rather, I periodically check the button using a timer ISR (ie: polled).

 

I'm not saying it's the most efficient method - it's just another method.

Link to post
Share on other sites

#include 


unsigned int counter=0;

int main(void)
{
   WDTCTL = WDTPW + WDTHOLD;// Stop watchdog timer

   P1DIR |= BIT0+BIT6;      // Set P1.0 to output direction
   P1OUT &= ~(BIT0+BIT6);   // set P1.0 to 0 (LEDs OFF)


while (1) // Infinite Loop
   {
   //pressing the button you add +1 to the counter every 10 msec.
   //If counter < 20 (200msecs = 0.2sec), normal press, green led lights on. 
   //If counter > 200 (2000msecs = 2sec), extended press, red led lights on.
   if ((BIT3 & P1IN) == 0)           // active low switch
      {counter++;
       __delay_cycles(10000);} //10000 delay cycles / ~1MHz = ~10 msec
   else if (0 < counter && counter < 20) //gotta love google
      {P1OUT ^= BIT6;
       counter = 0;}
   else if (counter >= 200)
      {P1OUT ^= BIT0;
       counter = 0;}  
   else if (counter >200)       //some help if things get stuck  (and they probably will)
      {counter = 0;}        
   }
}

 

Well, it works, though the long press is longer than what I had calculated it should be for some reason.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...