|
|
View previous topic :: View next topic |
Author |
Message |
Tuned Guest
|
4x4 keypad trouble! |
Posted: Sat Nov 20, 2004 10:03 am |
|
|
Hi, i am trying to use a LCD with a generic 4x4 keypad on a pic 16f876 at 4Mhz. The LCD works, but inthe ccs example code ex_lcdkb, the keypad, doesnīt. The LCD is in port D and the keypad on port B. Iīve found the code below for keypad interfacing, but it doesīt work, also Iīve tried to modify kbd.c to work with a 4x4 keypad unsuccesfully.
This is the code:
Code: |
#byte kbd = 0xF81 // This puts the entire structure
#define set_tris_kbd(x) set_tris_b(x)
//Keypad connection: (for example column 0 is B2)
// Bx:
#define COL0 (1 << 0) //1
#define COL1 (1 << 1) //10
#define COL2 (1 << 2) //100
#define COL3 (1 << 3) //1000
#define ROW0 (1 << 4) //10000
#define ROW1 (1 << 5) //100000
#define ROW2 (1 << 6) //1000000
#define ROW3 (1 << 7) //10000000
// The following bitmasks are the same as the above,
// but written in a different format.
#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2|COL3)
// Keypad layout:
char const KEYS[4][4] = {{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}};
#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() {
//port_b_pullups(false);
}
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 : set_tris_kbd(ALL_PINS&~COL0);
kbd=~COL0&ALL_PINS;
break;
case 1 : set_tris_kbd(ALL_PINS&~COL1);
kbd=~COL1&ALL_PINS;
break;
case 2 : set_tris_kbd(ALL_PINS&~COL2);
kbd=~COL2&ALL_PINS;
break;
case 3 : set_tris_kbd(ALL_PINS&~COL3);
kbd=~COL3&ALL_PINS;
break;
}
if(kbd_down) {
if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
kbd_down=FALSE;
kchar=last_key;
last_key='\0';
}
}
else {
if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
if((kbd & ROW0)==0)
row=0;
else if((kbd & ROW1)==0)
row=1;
else if((kbd & ROW2)==0)
row=2;
else if((kbd & ROW3)==0)
row=3;
last_key =KEYS[row][col];
kbd_down = TRUE;
}
else {
++col;
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
set_tris_kbd(ALL_PINS);
return(kchar);
}
|
If anyone could help me y would apreciate it. Thanks. |
|
|
J_Purbrick
Joined: 16 Sep 2003 Posts: 9
|
|
Posted: Sat Nov 20, 2004 10:56 am |
|
|
Here's a routine that I wrote for a PIC16F877. In this case I didn't want the ASCII values of the pushbuttons, but 0, 1, 2 etc for the numeric ones, 0xA, 0xB etc for the letters ABCD and 0xE for *, 0xF for #. The arrangement of the buttons is
1 2 3 A
4 5 6 B
7 8 9 C
* 0 # D
The rows (top-bottom) are on bits 4-7, and the columns (right to left, I forget why) should have been on bits 0-3, but the processor was programmed usiing the 5 volt method, which means that bit 3 of port B isn't usable, so bit 2 of port A is used instead. It should be easy to see how to make it work entirely with port B. The code could be more efficient, but it works. You need to enable the weak pullups for port B.
Code: |
// For remapping pushbuttons
int const remap[16] = {1, 2, 3, 0xA, 4, 5, 6, 0xB, 7, 8, 9, 0xC, 0xE, 0, 0xF, 0xD};
int read_keypad(void)
{
int d, button;
portb = 0;
bit_clear(trisb, 0);
d = portb & 0xF0; // Top 4 bits of port B
bit_set(trisb, 0);
if (d != 0xF0) // ABCD pressed
d = d + 1;
else // Not ABCD
{
bit_clear(trisb, 1);
d = portb & 0xF0; // Top 4 bits of port B
bit_set(trisb, 1);
if (d != 0xF0) // 369# pressed
d = d+2;
else // Not 369#
{
bit_clear(trisb, 2);
d = portb & 0xF0; // Top 4 bits of port B
bit_set(trisb, 2);
if (d != 0xF0) // 2580 pressed
d = d + 3;
else // Not 2580
{
bit_clear(trisa, 2);
bit_clear(porta, 2);
d = portb & 0xF0; // Top 4 bits of port B
bit_set(trisa, 2);
}
}
}
button = 0xFF;
if (!bit_test(d,4))
button = 0; // Top row
else if (!bit_test(d,5))
button = 4; // 2nd row
else if (!bit_test(d,6))
button = 8; // 3rd row
else if (!bit_test(d,7))
button = 12; // Bottom row
if (button != 0xFF) // Anything pressed?
{
button += (d & 3);
button = remap[button];
}
return(button);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Nov 20, 2004 11:19 am |
|
|
Just a couple things -- I didn't check your entire program but:
The following line is for an 18F PIC. The CCS example file has
some conditional statements at the start of the file. You've removed
the line that is needed for your 16F PIC and left in the 18F line.
The address of Port B in a 16F PIC is 0x06. You need to fix this.
The 2nd thing is that pull-ups are required for the keypad.
You need to un-comment the statement that enables port B pullups. |
|
|
Tuned Guest
|
|
Posted: Sat Nov 20, 2004 11:25 am |
|
|
Thanks for your help, but in this case I need the ascii values of the buttons.Also what I need is to adapt the kbd.c routine to work with an 4x4 keypad on port B, something like the code I posted.
Thanks again, itīs nice to see thereīs people who still help each other. |
|
|
Tuned Guest
|
|
Posted: Sat Nov 20, 2004 11:37 am |
|
|
Yes, the problem was #byte kbd=0xF81, that was for 18f MCUs. As soon as I changed that, the program started to work.
Thanks to all! |
|
|
buckeyes1997 Guest
|
what is correct |
Posted: Mon Nov 22, 2004 9:29 am |
|
|
what did you change the f81 value to to make it work?
matt |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Nov 22, 2004 10:30 am |
|
|
Read PCM's post
Quote: | The following line is for an 18F PIC. The CCS example file has
some conditional statements at the start of the file. You've removed
the line that is needed for your 16F PIC and left in the 18F line.
The address of Port B in a 16F PIC is 0x06. You need to fix this.
Quote:
#byte kbd = 0xF81
|
So the answer is 0x06 |
|
|
|
|
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
|