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 support@ccsinfo.com

Single Button Counter

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







Single Button Counter
PostPosted: Thu Oct 02, 2008 7:18 am     Reply with quote

Anybody know any program for a pushbutton to make counter on LCD?

And how to make it read during button_Released or during button_pushed?
TQ
Guest








PostPosted: Thu Oct 02, 2008 3:24 pm     Reply with quote

you can either use interrupt on portb - #int_rb
or external trigger - setup_ext_int
or ccp module in capture mode
Guest








PostPosted: Thu Oct 02, 2008 3:25 pm     Reply with quote

sorry,
external interrupt is ext_int_edge() function
cascaded
Guest







PostPosted: Thu Oct 02, 2008 5:51 pm     Reply with quote

Can anybody give coding example or tutorial?
PCM programmer



Joined: 06 Sep 2003
Posts: 21658

View user's profile Send private message

PostPosted: Fri Oct 03, 2008 6:22 pm     Reply with quote

Mark has some code for this in the Code Library:
http://www.ccsinfo.com/forum/viewtopic.php?t=22145

See the code posted below. It has been modified so it will work with
a 4 MHz crystal. It also has the bug-fix incorporated into it that was
mentioned in one of the replies to Mark's original post. It also uses
the "Flex" LCD driver from the Code Library forum.

I don't really want to do any more work on this for you. You must write
your own code. If the code posted below seems too complicated then
look at these other links for a few more examples:

Here is the "Button Command" code that I wrote for the Code Library:
http://www.ccsinfo.com/forum/viewtopic.php?t=23837
Here's a version of it that polls the buttons during a timer interrupt:
http://www.ccsinfo.com/forum/viewtopic.php?t=31849

Here is another button debounce program that's even more simple:
http://www.ccsinfo.com/forum/viewtopic.php?t=19874

Mark's code (modified slightly, as listed above):
Code:

// Multi-Event Switch Action for Microchip Microcontrollers 

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

#include "flex_lcd.c"

#define CLICK_TIME       250  // Time to press/release a click in ms
#define DBL_CLICK_TIME   500  // Time to wait for a dbl_click in ms
#define SWITCH_READ_TIME  10  // Interval to read the switches in ms

#define NUM_SWITCHES  2      // Max 8 switches


#define SW0_PIN  PIN_A4
#define SW1_PIN  PIN_B0

#define LED0 PIN_B3
#define LED1 PIN_B2


// Different types of click events
enum SWITCH_STATES
{
  SWITCH_IDLE,
  SWITCH_DOWN,
  SWITCH_HELD,
  SINGLE_CLICK,
  DOUBLE_CLICK
};

int8 Miliseconds;
int8 Read_Switch_Timer = 0;
int1 Read_Switch_Flag = FALSE;
int16 Click_Timer[NUM_SWITCHES];
enum SWITCH_STATES Switch_State[NUM_SWITCHES];

//--------------------------------------------------
#int_timer2
void timer2_isr(void)
{
  if (Miliseconds < 0xFF)
    Miliseconds++;
}

//--------------------------------------------------
void Switch_Released(int8 number)
{
  // Make sure this is a valid switch
  if (number < NUM_SWITCHES)
  {
    switch (Switch_State[number])
    {
      case SWITCH_DOWN:
        // Set the timer to the maximum time between a press and release to
        // consider this a single click
        Click_Timer[number] = CLICK_TIME;
        Switch_State[number] = SINGLE_CLICK;
        break;

      case SWITCH_HELD:
        // Just set the timer to a small number so that it will fire as soon
        // as we release the switch
        Click_Timer[number] = 1;
        // Don't change the state here, the timers will take care of it
        break;

      case SINGLE_CLICK:
        // Set the timer for the maximum time we will wait for a double click
        Click_Timer[number] = DBL_CLICK_TIME;
        Switch_State[number] = DOUBLE_CLICK;
        break;

      case DOUBLE_CLICK:
        // The user is just clicking away at the button.  We won't really do
        // until he stops or we could cancel the operation by setting the state
        // to idle and the timer to 0
        Click_Timer[number] = DBL_CLICK_TIME;
        Switch_State[number] = DOUBLE_CLICK;
        break;

      default:
        Click_Timer[number] = 0;
        Switch_State[number] = SWITCH_IDLE;
        break;
    }
  }
}


//--------------------------------------------------
void Switch_Pressed(int8 number)
{
  // Make sure this is a valid switch
  if (number < NUM_SWITCHES)
  {
    // Set the state to down only if we haven't just processed a click
    if (Switch_State[number] == SWITCH_IDLE)
      Switch_State[number] = SWITCH_DOWN;
    Click_Timer[number] = DBL_CLICK_TIME;
  }
}

//--------------------------------------------------
// Handles debouncing of the switches
void Switch_Read_Value(void)
{
  static int8 last_read = 0xFF;
  static int8 last_state = 0xFF;
  static int8 debounce_count;
  int8 result = 0xFF;
  int8 i;
  int8 changed;


  if (!input(PIN_A4))
    bit_clear(result,0);

  if (!input(PIN_B0))
    bit_clear(result,1);

  // See if it changed
  if (result != last_read)
  {
    // It did so debounce it
    debounce_count = 5;
    last_read = result;
  }
  // We are debouncing
  else if (debounce_count)
  {
    debounce_count--;
    // Done debouncing
    if (debounce_count == 0)
    {
      // See if the state of the switch has changed
      changed = (result ^ last_state);
      // Determine what type of event occurred
      for(i=0;i<8;i++)
      {
        if (bit_test(changed,i))
        {
          if (bit_test(result,i))
            Switch_Released(i);
          else
            Switch_Pressed(i);
        }
        // Save the current state
        last_state = result;
      }
    }
  }
}

//--------------------------------------------------------------
// What we do if a switch was pressed longer than the click time
void Switch_Pressed_Event(int8 number)
{
  // TO ADD MORE SWITCHES you need to add the cases
  switch(number)
  {
    case 0:
      // Light an LED on RB3 of the picdem2 plus board
      output_high(LED0);
      printf(lcd_putc,"\fSW1 Pressed");
      break;
   case 1:
      // Light an LED on RB2 of the picdem2 plus board
      output_high(LED1);
      printf(lcd_putc,"\fSW2 Pressed");
     break;
   default:
     break;
  }
}

//-----------------------------------------------------------------
// What we do if a switch was pressed and held longer than the click time
// and then released
void Switch_Release_Event(int8 number)
{
  // TO ADD MORE SWITCHES you need to add the cases
  switch(number)
  {
    case 0:
      // Turn off the LED on RB3 of the picdem2 plus board
      output_low(LED0);
      printf(lcd_putc,"\fSW1 Released");
      break;
   case 1:
      // Turn off the LED on RB2 of the picdem2 plus board
      output_low(LED1);
      printf(lcd_putc,"\fSW2 Released");
     break;
   default:
     break;
  }
}

//----------------------------------------------------------------
// What we do on a single click
void Single_Click_Event(int8 number)
{
  // TO ADD MORE SWITCHES you need to add the cases
  switch(number)
  {
    case 0:
      // Light an LED on RB3 of the picdem2 plus board
      output_high(LED0);
      if (Switch_State[1] == SWITCH_HELD)
        printf(lcd_putc,"\fSW1 Click\nWhile SW2 Held");
      else
        printf(lcd_putc,"\fSW1 Click");
      break;
   case 1:
      // Light an LED on RB2 of the picdem2 plus board
      output_high(LED1);
      if (Switch_State[0] == SWITCH_HELD)
        printf(lcd_putc,"\fSW2 Click\nWhile SW1 Held");
      else
        printf(lcd_putc,"\fSW2 Click");
     break;
   default:
     break;
  }
}

//----------------------------------------------------
void Double_Click_Event(int8 number)
{

switch(number)
  {
   case 0:
      // Turn off the LED on RB3 of the picdem2 plus board
      output_low(LED0);
      if (Switch_State[1] == SWITCH_HELD)
        printf(lcd_putc,"\fSW1 Dbl_Click\nWhile SW2 Held");
      else
        printf(lcd_putc,"\fSW1 Dbl_Click");
      break;
   case 1:
      // Turn off the LED on RB2 of the picdem2 plus board
      output_low(LED1);
      if (Switch_State[0] == SWITCH_HELD)
        printf(lcd_putc,"\fSW2 Dbl_Click\nWhile SW1 Held");
      else
        printf(lcd_putc,"\fSW2 Dbl_Click");
     break;
   default:
     break;
  }
}

//---------------------------------------------------
void Switch_Timers(void)
{
int8 i;

if(Read_Switch_Timer == 0)
   Read_Switch_Flag = TRUE;
else
   Read_Switch_Timer--;


for(i=0; i<NUM_SWITCHES; i++)
   {
    if(Click_Timer[i])
      {
       Click_Timer[i]--;
   
       if(Click_Timer[i] == 0)
         {
          switch (Switch_State[i])
            {
             case SWITCH_DOWN:
               Switch_Pressed_Event(i);
               Switch_State[i] = SWITCH_HELD;
               break;

             case SWITCH_HELD:
               Switch_Release_Event(i);
               Switch_State[i] = SWITCH_IDLE;
               break;

             case SINGLE_CLICK:
               Single_Click_Event(i);
               Switch_State[i] = SWITCH_IDLE;
               break;

             case DOUBLE_CLICK:
               Double_Click_Event(i);
               Switch_State[i] = SWITCH_IDLE;
               break;

             default:
               Switch_State[i] = SWITCH_IDLE;
               break;
            }
         }
      }
   }
}


// Handles all our switch tasks
void Switch_Tasks(void)
{
  if (Read_Switch_Flag)
  {
    Switch_Read_Value();
    Read_Switch_Timer = SWITCH_READ_TIME;
    Read_Switch_Flag = FALSE;
  }
}

//---------------------------------
// System counter
void System_Tick(void)
{
  while (Miliseconds)
  {
    Switch_Timers();
    Miliseconds--;
  }
}


//=======================================================
void main (void)
{
  int8 i;

  // Initialize all of the timers and states
  for(i=0; i<NUM_SWITCHES; i++)
     {
      Click_Timer[i] = 0;
      Switch_State[i] = SWITCH_IDLE;
     }
     
  setup_timer_2(T2_DIV_BY_4, 250, 1);  // Interrupt every 1ms
  enable_interrupts(INT_TIMER2);
  enable_interrupts(GLOBAL);
  lcd_init();
 
  printf(lcd_putc,"PICDEM Switch\nEvent Test");
 
  Miliseconds = 0;

  while(1)
  {
   System_Tick();
   Switch_Tasks();
  }

}
Guest








PostPosted: Sat Oct 04, 2008 7:30 am     Reply with quote

Thanks. That's what i'm looking for. TQ Very Happy
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