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

complete listing - interrupt driven keypad routine

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
newguy



Joined: 24 Jun 2004
Posts: 1442
Location: Edmonton, Alberta

View user's profile Send private message

complete listing - interrupt driven keypad routine
PostPosted: Thu Jun 24, 2004 1:43 pm     Reply with quote

As per the suggestion in the discussion forum, I'm also posting this here.

Hi everyone,

Yesterday I asked about an interrupt driven (RB interrupt) keypad routine - I sorted it all out, and thought I'd share what I came up with in case anyone else needs something similar. PCM programmer - thanks for your input.

The keypad is just an array of 16 pushbuttons hooked up to port b. If you want to see the schematic, just go to http://www.melabs.com/downloads/labx1sch.pdf

The code I wrote is for the full 16 button keypad, although for my present application, I only need 12 buttons. The reason that I came up with this routine is that for the application I'm working on, I need to detect multiple button presses and releases simultaneously. There's a possibility that the user of the finished product could press & hold several buttons simultaneously, and I didn't want to tie up the processor by constantly polling port b to detect changes.

The one weak point is that the routine can't detect changes on "columns". have a look at the schematic above and you'll see what I mean. If the user presses and holds say, button 1, and then presses button 5 (same column), the processor won't detect that change since both are hooked up to pin b4. However, if the user simultaneously presses buttons 1 & 5, this routine will pick that up. To overcome this weakness, I'm going to simply place the 4 buttons in my product that can be pressed & held simultaneously on four different columns (b4 - b7). The routine will then be able to distinguish what was pressed, when it was pressed, and when it was released without continuous polling of port b.

Anyway, here it is. 18F452, clocked at 4 MHz. I've left off the lcd routines though, for brevity. Take it easy on me - my code isn't nearly as "eloquent" as some of the stuff I've seen posted here. Razz


Code:
#byte portb = 0xf81
#use fast_io(B)

int1 key_pressed = FALSE;
static int old_b_state;
static int16 key = 0;

void find_key(void) {
   int pin, b_state, delay = 10;
   delay_ms(50);  // debounce
   disable_interrupts(INT_RB);
   pin = 4;
   if (!bit_test(old_b_state,pin)) {
      portb = 0xf1;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 0);
      }
      portb = 0xf2;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 4);
      }
      portb = 0xf4;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 8);
      }
      portb = 0xf8;
      delay_us(delay);
      b_state = portb;
      if(bit_test(b_state,pin)) {
         bit_set(key, 12);
      }
   }
   pin = 5;
   if (!bit_test(old_b_state,pin)) {
      portb = 0xf1;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 1);
      }
      portb = 0xf2;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 5);
      }
      portb = 0xf4;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 9);
      }
      portb = 0xf8;
      delay_us(delay);
      b_state = portb;
      if(bit_test(b_state,pin)) {
         bit_set(key, 13);
      }
   }
   pin = 6;
   if (!bit_test(old_b_state,pin)) {
      portb = 0xf1;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 2);
      }
      portb = 0xf2;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 6);
      }
      portb = 0xf4;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 10);
      }
      portb = 0xf8;
      delay_us(delay);
      b_state = portb;
      if(bit_test(b_state,pin)) {
         bit_set(key, 14);
      }
   }
   pin = 7;
   if (!bit_test(old_b_state,pin)) {
      portb = 0xf1;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 3);
      }
      portb = 0xf2;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 7);
      }
      portb = 0xf4;
      delay_us(delay);
      b_state = portb;
      if (bit_test(b_state,pin)) {
         bit_set(key, 11);
      }
      portb = 0xf8;
      delay_us(delay);
      b_state = portb;
      if(bit_test(b_state,pin)) {
         bit_set(key, 15);
      }
   }
   portb = old_b_state;
   enable_interrupts(INT_RB);
}

void print_key(void) {
   int i;
   if (key != 0) {
      lcd_putc("\f");
      for (i = 0; i < 16; i++) {
         if (bit_test(key,i)) {
            printf(lcd_putc,"%u,",i+1);
         }
      }
      key = 0;
   }
}

#int_RB
void RB_isr(void) {
   if (old_b_state != portb) {
      old_b_state = portb;
      key_pressed = TRUE;
   }
}



void main() {

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_ON);
   setup_timer_0(RTCC_INTERNAL|RTCC_OFF);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   enable_interrupts(INT_RB);
   enable_interrupts(global);

   port_b_pullups(TRUE);
   output_b(0xf0);
   set_tris_b(0xf0);

   set_tris_e(0x00);

   lcd_init();
   lcd_putc("Ready");

   old_b_state = portb;

   while (TRUE) {
      restart_wdt();
      if (key_pressed) {
         key_pressed = FALSE;
         find_key();
      }
      print_key();
   }

}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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