CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

timed pushbutton ISR

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rret



Joined: 01 Dec 2009
Posts: 9
Location: sherman CT

View user's profile Send private message

timed pushbutton ISR
PostPosted: Tue Dec 01, 2009 8:17 pm     Reply with quote

I am trying to find CCS code that when a pushbutton is pushed an interrupt service routine is called. That ISR can then distinquish whether or not the button was pushed momentarily or was held down for 3 seconds. It also does debouncing. I have searched and searched but have not found anything. Can someone help me out please?
PS - I have tried "rolling my own", but the B0 PIN status can't seem to be determined in my ISR, thus I have no idea how long the button was held down.
MiniMe



Joined: 17 Nov 2009
Posts: 50

View user's profile Send private message

PostPosted: Wed Dec 02, 2009 2:13 am     Reply with quote

Well first of all ...
-----

Code:
#INT_RB   ----  Port B any change on B4-B7

You may find very useful a CCS manual ... a help file. Probably you will find that interrupt is only on a whole 4 pins (4-7) on port B and C

and

Code:
#int_RB
RB_isr()  { Function }


Second
-----

Code:
   port_b_pullups(TRUE);
   set_tris_b(0b00000000);


Third
-----

Use Timer interrupts

Code:
#int_RTCC
RTCC_isr() {function}

#int_timer2
...


Important
------

Do not forget to :
Code:

   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_RB);
   enable_interrupts(global);

Code:

setup_timer_0(RTCC_INTERNAL|RTCC_8_bit|RTCC_DIV_256);
and
set_timer0(0);

(to use timer) (try fo search for timer tutorial... help file may help also)


Search for every bit of code iv posted in a help file and you will find what you are looking for.

Everything else is up to you and your C language skills.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 02, 2009 5:45 pm     Reply with quote

Here's some code that I once did to detect if a button is being held down,
or has been pressed and released quickly. I don't really consider this
code to be finished. It does work. I tested it on a PicDem2-Plus.
I'm just posting it to give you some ideas on what has to be done to
detect if a switch is held down, or just pressed.

Also, Mark has written some code to solve the same problem.
See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=36222

Test program:
Code:

#include <16F877.h>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)

#define REC_SWITCH_PIN  PIN_A4

#define LED_PIN  PIN_B1

#include "switch.h"
#include "switch.c"

// This preset value for Timer0 (aka RTCC) will make it
// interrupt at a 100 Hz rate, with a 4 MHz oscillator.
#define RTCC_PRESET  (256 - 39) 

// This routine interrupts every 10 ms.  It's used to poll
// the switches.
#int_rtcc
void rtcc_isr(void)
{
set_rtcc(RTCC_PRESET);

update_switch_status();   // Poll the switches
}


//=====================================
void main(void)
{
output_low(LED_PIN);

// Read and save the initial state of the switches.
gc_old_switch_status = read_switches();

// Setup the RTCC for the 10ms timer tick that runs the multi-tasking.
// A pre-scaler of 256 gives 3906.25 Hz rtcc clock.
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
set_rtcc(RTCC_PRESET);
clear_interrupt(INT_RTCC);
enable_interrupts(INT_RTCC);

enable_interrupts(GLOBAL);

// If the "Rec" button is held down for 2 seconds, turn on the
// LED on pin B1.  If it's pressed and released (quickly) then
// turn the LED off.
while(1)
  {
   if((rec_button == SW_HELD))
      output_high(LED_PIN);
   else if(rec_button == SW_PRESSED)
      output_low(LED_PIN);
  }

}


Code:

// switch.c -- Debounces the switches.
// Return the status of the switches. A "1" bit value means
// the switch is open, and a "0" bit means the switch is pressed.
// (i.e., When a switch is pressed it puts Ground on the PIC pin).

SW_STATE read_switches(void)
{
SW_STATE switch_values;

switch_values = 0xFF;   // Init all switch values to "open"
switch_values.rec = input(REC_SWITCH_PIN);
return(switch_values);
}


// When the program starts, the button state will be initialized to "UP".
void update_switch_status(void)
{
SW_STATE current_switch_status;

// Read the switches.
current_switch_status = read_switches();

// If the switch is closed, then increment a counter.  Based on the
// value of the counter, set the switch status byte to "Pressed",
// "Down", or "Held Down".
if(current_switch_status.rec == SW_CLOSED)
  {
   if(gc_rec_button_counter != 0xFF)  // Limit count to 0xFF max
      gc_rec_button_counter++;        //  because it's a byte variable

   // Set the state, based on value of the down counter.
   // The down counter will be a value from 1 to 0xFF.
   if(gc_rec_button_counter == 1)
      gc_rec_button_state = SW_PRESSED;
   else if(gc_rec_button_counter < REC_SW_HELD_DOWN_DELAY)
      gc_rec_button_state = SW_DOWN;
   else
      gc_rec_button_state = SW_HELD;
  }
else  // If the switch is open:
  {
   if(gc_rec_button_counter)  // Has the rec sw. been down previously ?
      gc_rec_button_state = SW_RELEASED; // If so, show it is now released
   else
      gc_rec_button_state = SW_UP;  // If not, it's been up for at least 2+ ticks

   gc_rec_button_counter = 0;  // Always clear down ctr if switch is up.
  }



//----------------------------
// Tell the user code in main() that the buttons have been updated.

//gc_button_status_updated = TRUE;
gc_old_switch_status = current_switch_status;

}



Code:
// switch.h

#define REC_SW_HELD_DOWN_DELAY 200  // 200 x 10ms = 2 secs (Max = 2.55 sec)

// Logic levels for the switches.
#define SW_CLOSED 0
#define SW_OPEN   1

// The switch states are ordered 1 to 5 because we will clear the
// state variable to 0 in the user code to show that it has been read.
enum sw_states {SW_UP=1, SW_PRESSED, SW_DOWN, SW_HELD, SW_RELEASED};
//                1        2           3        4        5

//---------------------------------------------------------------------------
// GLOBALS
//
// This structure holds the state of the switches after they are read
// from the i/o port.
typedef struct
{
int8 rec;
}SW_STATE;

// These enum values provide names for the indexes into the array of
// gat_sw_info structures, below, instead of just using 0, 1, 2, 3, 4, 5.
enum switches {REC_SW};

struct
{
int8 state;         // This is either UP, PRESSED, DOWN, HELD, or RELEASED
int8 counter;       // Number of ticks that the switch has been held down.
}gat_sw_info[1] = {
 {0, 0}  // REC_SW
};

// This variable is used in the check_switches() function.
SW_STATE gc_old_switch_status = {SW_OPEN};

// Use macros to create easy-to-read names for the switch events.
#define gc_rec_button_counter  gat_sw_info[REC_SW].counter
#define gc_rec_button_state    (gat_sw_info[REC_SW].state)


// Short named versions of the button state variables
#define rec_button    (gat_sw_info[REC_SW].state)


int8 gc_button_status_updated = FALSE;

//---------------------------------------------------------------------------
// FUNCTION PROTOTYPES
SW_STATE read_switches(void);
rret



Joined: 01 Dec 2009
Posts: 9
Location: sherman CT

View user's profile Send private message

thanks, but one question at this point...
PostPosted: Fri Dec 04, 2009 2:47 pm     Reply with quote

to pcm-programmer-
thanks - i'll give that a try. i didnt need hints, i needed code, so thanks.
my only concern is that i will be receiving chars from the serial port at a high rate and i'm concerned that the timer interrupt may interfere with that??? your thoughts?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 04, 2009 2:49 pm     Reply with quote

I can't really answer without knowing the baud rate and the PIC's
oscillator frequency, and the PIC.
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Sat Dec 05, 2009 9:09 am     Reply with quote

You could do it by setting up a single interrupt only, running at a rate fast enough to poll the receive flag for any character that might have come in since the last interrupt. If a character has arrived, deal with it (if "dealing with it" takes too long, stuff it into a buffer to be dealt with in the main() routine).

Divide down the basic timer rate to get something suitable to deal with pushbuttons etc, and do what's necessary with the information.

This is the way I put together almost all the programs I write, and it always seems to work well. It avoids any uncertainty about which interrupt is delaying any other interrupt, and so forth.
rret



Joined: 01 Dec 2009
Posts: 9
Location: sherman CT

View user's profile Send private message

ended up doing this...
PostPosted: Wed Dec 09, 2009 12:35 pm     Reply with quote

thanks everyone for your help.

I ended up doing this, as i don't need to know if the button is up, just how long it was down.
(constructive criticism is welcome!)

Code:
// external interrupt when button pushed
#INT_EXT
void ext_isr()
{
   int16 count=0;
   
   while (input(PIN_B0) && count<LP_DELAY)
   {
      delay_ms(1);

      if (input(PIN_B0))
            ++count;
      else
      {
         if (count<10)
            count=0; //debounce
         else
            break;
      }
   }

   g_keypresstype = (count>10 && count<LP_DELAY)? QUICKPRESS:LONGPRESS;

}
MegatroniC



Joined: 08 Dec 2009
Posts: 35

View user's profile Send private message ICQ Number

PostPosted: Thu Mar 11, 2010 3:28 am     Reply with quote

PCM programmer wrote:
Here's some code that I once did to detect if a button is being held down,
or has been pressed and released quickly.


Is it possible to change this code and used the 3 button?
Thanks Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 11, 2010 12:43 pm     Reply with quote

Yes, it is possible.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group