newguy
Joined: 24 Jun 2004 Posts: 1908
|
complete listing - interrupt driven keypad routine |
Posted: Thu Jun 24, 2004 1:43 pm |
|
|
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.
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();
}
} |
|
|