View previous topic :: View next topic |
Author |
Message |
shroder300
Joined: 17 Jul 2006 Posts: 7
|
keypad problem |
Posted: Thu Nov 13, 2008 10:29 am |
|
|
First my keypad is a 4x4 matrix keypad with an extra common pin. I have it hooked to portb with pullups active. Upon a button press I get a col and row pin shorted to gnd indicating which button is pressed. I took newguy's interrupt code (http://www.ccsinfo.com/forum/viewtopic.php?t=19726) and modified it.
What I get is the button code press and then release. But I have to hold down the button to get the push and release code. If I quickly tap the key I only get the release code.
Is my keypad (all electronics) bad or my code wrong?
Code: |
/*============================================
pic16f877a keypad routine. 11/12/08
Jason Berkhimer
Keypad from all electronics. 4 col pins, 4 row pins and common. col and row
connected to portb and common to gnd. pullups active. keypad press detected
through interrupts.
============================================*/
#include <16F877A.h>
#fuses HS // fast oscillator
#fuses NOWDT // no watch dog timer
#fuses NOPROTECT // no code protection
#fuses NODEBUG // no debugger
#fuses NOPUT // no power up timer
#fuses NOBROWNOUT // no brown out reset
#fuses NOLVP // no low voltage programming
#fuses NOCPD // no EE memory protection
#fuses NOWRT //
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#byte porta = 0x05
#byte portb = 0x06
#byte portc = 0x07
#byte portd = 0x08
#byte porte = 0x09
#use fast_io(B)
// #include <stdlib.h>
// variables ===================================================================
int1 key_pressed = FALSE;
static int old_b_state, new_b_state;
static int16 key = 0;
char kchar;
// interrupts ==================================================================
#int_RB
void RB_isr(void) {
new_b_state = input_b();
if (old_b_state != new_b_state) {
old_b_state = input_b();
// if (old_b_state == 0xff)
key_pressed = TRUE;
}
}
// functions ===================================================================
void find_key(void) {
int pin, b_state, delay = 10;
disable_interrupts(INT_RB);
delay_ms(50); // debounce
b_state = portb;
printf("%X",b_state);
old_b_state=input_b();
enable_interrupts(INT_RB);
}
// main ========================================================================
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
port_b_pullups(TRUE);
delay_us(50); //wait for pullups to come on.
set_tris_b(0xff);
old_b_state = input_b(); //read portb before turning on int.
enable_interrupts(INT_RB);
enable_interrupts(global);
printf("keypad test");
while(TRUE)
{
if (key_pressed) {
key_pressed = FALSE;
find_key();
}
output_d(0x0);
delay_ms(250);
output_d(0x2);
delay_ms(250);
}
}
|
_________________ compiler PCM version 4.064 |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu Nov 13, 2008 10:56 am |
|
|
I would start by changing this
Code: |
void RB_isr(void) {
new_b_state = input_b();
if (old_b_state != new_b_state) { <---- Not required as this interrupted due to a change in state!
old_b_state = input_b();
// if (old_b_state == 0xff)
key_pressed = TRUE;
}
}
change to
void RB_isr(void) {
old_b_state = input_b();
if (old_b_state == 0xFF)
key_pressed = true;
}
|
You don't actually use the push code ?
I can't see what your problem is! |
|
|
shroder300
Joined: 17 Jul 2006 Posts: 7
|
|
Posted: Thu Nov 13, 2008 11:09 am |
|
|
Right now I am only printing the codes to the serial port.
My problem is the keypad buttons have to be held down for at least half a second before the program prints a press code and then release code (once the button is released). If I don't hold down the button I only get a release code on the serial port.
The changes you suggested didn't change the results at all. _________________ compiler PCM version 4.064 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 13, 2008 2:00 pm |
|
|
Look at this CCS example file on using push buttons with #int_rb:
Quote: | c:\program files\picc\examples\ex_pbutt.c |
It has an example of how to do the isr (for 'press' or 'release' but not both).
Your complaint about the requirement for a 500ms hold down time is
caused by the delays in your loop. Your program only tests the status
every 1/2 second. That's the update rate. |
|
|
Guest
|
|
Posted: Fri Nov 14, 2008 5:54 am |
|
|
thanks, I didnt think about that. should I be checking the status in the isr instead? |
|
|
shroder300
Joined: 17 Jul 2006 Posts: 7
|
|
Posted: Fri Nov 14, 2008 10:21 am |
|
|
Here is my final code. the int routine will pick up both a press and a release. the main function will only print a press, however.
Code: | /*==============================================================================
pic16f877a keypad routine. 11/12/08
Jason Berkhimer
keypad from all electronics. 4 col pins, 4 row pins and common. col and row
connected to portb and common to gnd. pullups active. keypad press detected
through interrupts. prints raw data from keypad to serial port and portd
==============================================================================*/
#include <16F877A.h>
#fuses HS // fast oscillator
#fuses NOWDT // no watch dog timer
#fuses NOPROTECT // no code protection
#fuses NODEBUG // no debugger
#fuses NOPUT // no power up timer
#fuses NOBROWNOUT // no brown out reset
#fuses NOLVP // no low voltage programming
#fuses NOCPD // no EE memory protection
#fuses NOWRT //
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#byte porta = 0x05
#byte portb = 0x06
#byte portc = 0x07
#byte portd = 0x08
#byte porte = 0x09
#use fast_io(B)
#use fast_io(D)
// #include <stdlib.h>
// variables ===================================================================
int1 key_pressed = FALSE;
static int old_b_state, new_b_state;
static int16 key = 0;
char kchar;
// interrupts ==================================================================
#int_RB
void RB_isr(void) { // detects both press and release
new_b_state = input_b();
if (new_b_state != old_b_state); // make sure state changed
key_pressed = TRUE;
old_b_state=new_b_state;
}
// functions ===================================================================
void find_key(void) {
int pin, b_state, delay = 10;
disable_interrupts(INT_RB);
delay_ms(50); // debounce
b_state = portb;
if (b_state != 0xff){ // only print on press
printf("-%X-",b_state);
output_d(b_state);
}
enable_interrupts(INT_RB);
}
// main ========================================================================
void main() {
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
port_b_pullups(TRUE);
delay_us(50); // wait for pullups to come on.
set_tris_b(0xff);
set_tris_d(0x00);
set_tris_c(0x00);
old_b_state = input_b(); // read portb before turning on int.
enable_interrupts(INT_RB);
enable_interrupts(global);
printf("keypad test");
while(TRUE)
{
if (key_pressed) {
key_pressed = FALSE;
find_key();
}
}
}
|
_________________ compiler PCM version 4.064 |
|
|
|