|
|
View previous topic :: View next topic |
Author |
Message |
krantz Guest
|
flexible 4x4 keypad driver |
Posted: Thu Feb 08, 2007 8:01 am |
|
|
Hi to all!
Anyone used this driver within isr ( in my case INT_RB).
I can input only keys on first column (col0).
Any help?
Thanks
Krantz |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Thu Feb 08, 2007 9:25 am |
|
|
Does it display results, but the wrong letter. OR nothing at all? |
|
|
krantz Guest
|
|
Posted: Thu Feb 08, 2007 11:16 pm |
|
|
Hi!
here the code in which during main, I to focus on keyboard input, it do a simple task.
The driver see only key press on first column of the matrix (col0) inputting however the right charachters ( I have '1' , '4' , '7' , 'A').
If I insert the call to kbd_getc(); directly in main ( as in the original example) without use of interrupt (int_rb) the driver work fine inputting all chars.
Many thanks!
#include "C:\Temp\TurboC\Mplab\16f877.h"
//Keypad connection:
#define row0 PIN_B4
#define row1 PIN_B5
#define row2 PIN_B6
#define row3 PIN_B7
#define col0 PIN_B0
#define col1 PIN_B1
#define col2 PIN_B2
#define col3 PIN_B3
char const KEYS[4][4] =
{{'1','2','3','F'},
{'4','5','6','E'},
{'7','8','9','D'},
{'A','0','B','C'}};
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void kbd_init()
{
//set_tris_b(0xF0);
//output_b(0xF0);
port_b_pullups(true);
}
short int ALL_ROWS (void)
{
if(input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
char kbd_getc()
{
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR)
{
switch (col)
{
case 0:
output_low(col0);
output_high(col1);
output_high(col2);
output_high(col3);
break;
case 1:
output_high(col0);
output_low(col1);
output_high(col2);
output_high(col3);
break;
case 2:
output_high(col0);
output_high(col1);
output_low(col2);
output_high(col3);
break;
case 3:
output_high(col0);
output_high(col1);
output_high(col2);
output_low(col3);
break;
}
if(kbd_down)
{
if(!ALL_ROWS())
{
kbd_down=false;
kchar=last_key;
last_key='\0';
}
}
else
{
if(ALL_ROWS())
{
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
}
else
{
++col;
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
//===========================
void main()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_RB);
kbd_init();
printf("\r\Starting ...");
while(TRUE)
{
output_high(PIN_d0);
delay_ms(300);
output_low(PIN_d0);
delay_ms(300);
}
}
#int_rb
int_rb_isr()
{
char k;
k=kbd_getc();
if(k!=0)
{
if(k=='*')
printf("%c", '*');
else
printf("%c", k);
}
} |
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
Posted: Fri Feb 09, 2007 8:35 am |
|
|
If it works by itself but not with the IRQ, then that would seem to be the problem.
Your int_Rb works by seeing a change on the upper nibble of port b. B4-B7...the rows
so in normal operation:
1. upper bits of port b are pulled up. These are the rows.
2. column are outputted as 0.
3. you press a key that will connect a row to column. That pulls a single row line to ground(0). That row(B4-B7) is seen by the IRQ. Then you can read/decode it.
I see you have two lines commented out in kpd_init.
Are you seeing any place in the code that doesn't look correct. |
|
|
krantz Guest
|
|
Posted: Sun Feb 11, 2007 11:57 pm |
|
|
Hi treitmey,
sorry for delay, but week end....!
The lines in keyb_init are commented in the original version of the driver and I got it as was, but after some tests it seems they shall be set in that mode to do work the driver .
To check for irq involvement on the problem, I've removed the int_rb and inserted the call to kbd_getc directly in main as shown.
In this test the driver doesn't capture any key press not even the keys on col0.
The only way I found to do work the driver is to remove also the on-off delay on
pin D0 as shown, and then the driver capture properly all the key presses .
I don't understand well how the driver works but it seems that it needs several passes to reach the condition (kbd_call_count>KBD_DEBOUNCE_FACTOR) and then decode the key.
Pheraps during the irq it doesn't has this chance, but I don't understand in the case of the on-off on pin D0 what could be the bug (perhaps the key press time width is less than 300+300 ms delay inserted !) .
Thanks again for support,
Krantz
#include "C:\Temp\TurboC\Mplab\16f877.h"
//Keypad connection:
#define row0 PIN_B4
#define row1 PIN_B5
#define row2 PIN_B6
#define row3 PIN_B7
#define col0 PIN_B0
#define col1 PIN_B1
#define col2 PIN_B2
#define col3 PIN_B3
char const KEYS[4][4] =
{{'1','2','3','F'},
{'4','5','6','E'},
{'7','8','9','D'},
{'A','0','B','C'}};
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void kbd_init()
{
//set_tris_b(0xF0);
//output_b(0xF0);
port_b_pullups(true);
}
short int ALL_ROWS (void)
{
if(input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
char kbd_getc()
{
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;
byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR)
{
switch (col)
{
case 0:
output_low(col0);
output_high(col1);
output_high(col2);
output_high(col3);
break;
case 1:
output_high(col0);
output_low(col1);
output_high(col2);
output_high(col3);
break;
case 2:
output_high(col0);
output_high(col1);
output_low(col2);
output_high(col3);
break;
case 3:
output_high(col0);
output_high(col1);
output_high(col2);
output_low(col3);
break;
}
if(kbd_down)
{
if(!ALL_ROWS())
{
kbd_down=false;
kchar=last_key;
last_key='\0';
}
}
else
{
if(ALL_ROWS())
{
if(!input (row0))
row=0;
else if(!input (row1))
row=1;
else if(!input (row2))
row=2;
else if(!input (row3))
row=3;
last_key =KEYS[row][col];
kbd_down = true;
}
else
{
++col;
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
//===========================
void main()
{
kbd_init();
printf("\r\Starting ...");
while(TRUE)
{
char k;
k=kbd_getc();
if(k!=0)
{
if(k=='*')
printf("%c", '*');
else
printf("%c", k);
//output_high(PIN_d0);
//delay_ms(300);
//output_low(PIN_d0);
//delay_ms(300);
}
}
} |
|
|
|
|
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
|