|
|
View previous topic :: View next topic |
Author |
Message |
newpic
Joined: 09 Aug 2005 Posts: 32
|
Keypad help. |
Posted: Tue Jun 07, 2011 2:53 pm |
|
|
I try to use the keypad 4x3 (digikey P/N: GH5001-ND). I have the PIC Demo Z board and connect to the keypad to the PORTB, I also have a 7-segment on PORTD. Anytime the keypad pressed, I want to display the result on to the 7-segment.
I try to modify the kbd.c file that came with the compiler to use as driver. Does anyone have this driver works.
I know that my 7-segment function display_number(k);
works fine when I display the debug number, it displays ok.
Please help me. Thanks in advances.
here are my code:
main.c Code: | //main.c
#include <prototype.h>
#include <kbd.c>
char temp = 5; //debug only
char counter = 0;
//void display_number(char digit);
/* PROTOTYPE -- Display to 7-segment */
void display_number(char digit)
{
output_d(Digit_Map[digit]); output_low(DIGIT1);
delay_ms(4);
output_high(DIGIT1);
}
// main.c start here
main(void)
{
char k;
port_b_pullups(true);
kbd_init();
while(1)
{
// counter = 2; //debug only
// display_number(counter); // debug only
k = kbd_getc();
display_number(k);
delay_ms(10);
}
} |
prototype.h file
Code: | #include <18F4620.h>
#device ICD=TRUE //ADC=10
#fuses XT, NOLVP, NOWDT, NOXINST
#use delay (clock=4000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
//===================================================
// This is for isi_7_segment only
/*
output_high(PIN_D1); //a
output_high(PIN_D0); //b
output_high(PIN_D3); //c
output_high(PIN_D2); //d
output_high(PIN_D5); //e
output_high(PIN_D4); //f
output_high(PIN_D7); //g
*/
// 0 1 2 3 4 5 6 7 8 9
const char Digit_Map[10] = {0x7F,0x49,0xE7,0xCF,0xD9,0xDE,0xFE,0x4B,0xFF,0xDF};
// Digits
#define DIGIT3 PIN_A3
#define DIGIT2 PIN_A4
#define DIGIT1 PIN_A5
//===============================================================
//PICDemo Z
#define S2 PIN_B5
#define S3 PIN_B4
#define D1 PIN_A0
#define D2 PIN_A1
|
kbd.c file
Code: | ///////////////////////////////////////////////////////////////////////////
//// KBDD.C ////
//// Generic keypad scan driver ////
//// ////
//// kbd_init() Must be called before any other function. ////
//// ////
//// c = kbd_getc(c) Will return a key value if pressed or /0 if not ////
//// This function should be called frequently so as ////
//// not to miss a key press. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
////////////////// The following defines the keypad layout on port D
// Un-comment the following define to use port B
#define use_portb_kbd TRUE
// Make sure the port used has pull-up resistors (or the LCD) on
// the column pins
#if defined(__PCH__)
#if defined use_portb_kbd
#byte kbd = 0xF81 // This puts the entire structure
#else
#byte kbd = 0xF83 // This puts the entire structure
#endif
#else
#if defined use_portb_kbd
#byte kbd = 6 // on to port B (at address 6)
#else
#byte kbd = 8 // on to port D (at address 8)
#endif
#endif
#if defined use_portb_kbd
#define set_tris_kbd(x) set_tris_b(x)
#else
#define set_tris_kbd(x) set_tris_d(x)
#endif
//Keypad connection: (for example column 0 is B2)
// Bx:
#ifdef blue_keypad ///////////////////////////////////// For the blue keypad
#define COL0 (1 << 2)
#define COL1 (1 << 3)
#define COL2 (1 << 6)
#define ROW0 (1 << 4)
#define ROW1 (1 << 7)
#define ROW2 (1 << 1)
#define ROW3 (1 << 5)
#else ////////////////////////////////////////////////// For the black keypad
#define COL0 (1 << 5)
#define COL1 (1 << 6)
#define COL2 (1 << 7)
#define ROW0 (1 << 1)
#define ROW1 (1 << 2)
#define ROW2 (1 << 3)
#define ROW3 (1 << 4)
#endif
#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)
#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2)
// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
#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() {
}
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;
}
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==3)
col=0;
}
}
kbd_call_count=0;
}
set_tris_kbd(ALL_PINS);
return(kchar);
}
| [/code] |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
newpic
Joined: 09 Aug 2005 Posts: 32
|
keypad help |
Posted: Tue Jun 07, 2011 10:19 pm |
|
|
I try that and it still does nothing. I try to debug and watch the char k in the watch window and it always display '0' no matter what number I pressed.
I noticed that kbd.c file, the kbd_init() does not show any statement at all and this is what it came with the compiler.
Help need. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jun 07, 2011 10:40 pm |
|
|
Look at the while() loop in this CCS example file:
Quote: | c:\program files\picc\examples\ex_lcdkb.c |
It shows how to call the kbd_getc() function. You must test the return
value to see if it's non-zero. If it's non-zero, then you can use it.
You need to write your code in the same way. Also, don't attempt to
step through the code in a debugger. Just run it. |
|
|
newpic
Joined: 09 Aug 2005 Posts: 32
|
KEYPAD |
Posted: Wed Jun 08, 2011 2:42 pm |
|
|
I still get nothing from k=kbd_getc().
I decide to change to flex_bcd.c as follow Code: | //Keypad connection:
#define col0 PIN_B4
#define col1 PIN_B5
#define col2 PIN_B6
#define row0 PIN_B0
#define row1 PIN_B1
#define row2 PIN_B2
#define row3 PIN_B3
// Keypad layout:
char const KEYS[4][3] = {{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}};
#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(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);
break;
case 1 : output_high(col0);
output_low(col1);
output_high(col2);
break;
case 2 : output_high(col0);
output_high(col1);
output_low(col2);
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==3)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
|
main.c
Code: | //main.c
#include <prototype.h>
#include <flex_kbd.c>
char temp = 245; //debug only
char counter = 0;
//void display_number(char digit);
/* PROTOTYPE -- Display to 7-segment */
void display_number(char digit)
{
output_d(Digit_Map[digit]);
output_low(DIGIT1);
delay_ms(100);
output_high(DIGIT1);
}
// main.c start here
main(void)
{
char k;
kbd_init();
while(1)
{
k=kbd_getc();
k=kbd_getc();
if(k!=0)
if(k=='*')
display_number(0x7F); //0x7F is 0 per my Digit_Map[]
else
display_number(k);
delay_ms(10);
}
} |
if I pressed 1 on the keypad, I got on the 7-seg is junk (segment e,f,g lit up) it is not a 1. I have my keypad pin wire as follow
Quote: | 1 ----B0
2----B1
3----B2
4----B3
5----B4
6----B5
7----B6 |
Any suggestion will be appreciate. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Wed Jun 08, 2011 3:11 pm |
|
|
Hint:
Is the text character '1', the same as the number 1.....
Best Wishes |
|
|
newpic
Joined: 09 Aug 2005 Posts: 32
|
|
Posted: Thu Jun 09, 2011 1:34 pm |
|
|
I guess they are different
I couldn't make the kbd.c driver to work,
I try to use
Code: |
k = kbd_getc();
k=k-'0'; %Subtract value of '0' to convert to number.
display_number(k);
|
but it makes no difference.
what else could it be?
so I mod. the main code and create kbd_driver.c as follow and it does display ok when the specific key pressed. It is more for debug because it will scans multiple times from the main loop. If this is a long program it will miss the key pressed.
Note: I also change keypad connection to different pins instead of portb so I can use B6 for debug and steping through the code.
main.c
Code: | //main.c
#include <prototype.h>
#include <kbd_driver.c>
//void display_number(char digit);
/* PROTOTYPE -- Display to 7-segment */
void display_number(char digit)
{
output_d(Digit_Map[digit]);
output_low(DIGIT2);
delay_ms(1);
output_high(DIGIT2);
}
// main.c start here
void main(void)
{
char k;
char last_k;
while(1)
{
init();
k = get_key1();
k = get_key2();
k = get_key3();
last_k = k;
display_number(k);
}
} |
kbd_driver.c
Code: | //Keypad connection:
#define col0 PIN_B0
#define col1 PIN_B1
#define col2 PIN_B2
#define row0 PIN_C2
#define row1 PIN_C1
#define row2 PIN_C0
#define row3 PIN_A2
void init()
{
// port_b_pullups(true);
// output_high(row0);
output_c(0x00);
set_tris_c(0xff);
}
char get_key1()
{
char k;
output_high(col0); // scan column 0
if(input(row0))
{
k = 1;
}
else if(input(row1))
{
k = 4;
}
else if(input(row2))
{
k = 7;
}
output_low(col0); // column 0 off
return (k);
}
char get_key2()
{
char k;
output_high(col1); // scan column 1
if(input(row0))
{
k = 2;
}
else if(input(row1))
{
k = 5;
}
else if(input(row2))
{
k = 8;
}
output_low(col1); // column 1 off
return (k);
}
//=========
char get_key3()
{
char k;
output_high(col2); // scan column 2
if(input(row0))
{
k = 3;
}
else if(input(row1))
{
k = 6;
}
else if(input(row2))
{
k = 9;
}
output_low(col2); // column 2 off
return (k);
} |
I still want to use the kbd.c to work but out of idea, I would appreciate if anyone can pin point to my problems. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 09, 2011 1:53 pm |
|
|
Quote: | GH5001
I still want to use the kbd.c to work but out of idea, I would appreciate if
anyone can pin point to my problems.
|
I have that keypad. What's your compiler version ? |
|
|
newpic
Joined: 09 Aug 2005 Posts: 32
|
|
Posted: Thu Jun 09, 2011 2:42 pm |
|
|
I have Code: | CCS PCH C Compiler, Version 3.207, 24657
MPLAB 8.60 |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 09, 2011 3:25 pm |
|
|
I don't have the PCH compiler for vs. 3.207, but I do have the PCM
compiler for that version. So I made a test program for the 16F877 and it
works. It displays this on the TeraTerm window when I press each key:
This was tested on a PicDem2-Plus board (non-Rohs version) with the
GH5001 keypad, with your same connections. Here's the test program:
Code: |
#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define use_portb_kbd 1
#include <kbd.c>
//==========================================
void main()
{
int8 k;
port_b_pullups(TRUE);
kbd_init();
while(1)
{
k = kbd_getc();
if(k!=0)
putc(k);
}
} |
The closest version I have to 3.207 of PCH is vs. 3.230. That's not close
enough to be worth trying. Vs. 3.200 was a large revision point by CCS.
It's possible that 3.207 is buggy for your PIC. You could add the
NOPBADEN fuse, which will make sure that PortB comes up as digitial
i/o, instead of analog:
Quote: |
#include <18F4620.h>
#device ICD=TRUE //ADC=10
#fuses XT, NOLVP, NOWDT, NOXINST,NOPBADEN
#use delay (clock=4000000)
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)
|
Also, I would get rid of the #device ICD=TRUE and just run the code in
standalone mode. Don't try to debug it or step through the code. See
if it works.
If you have a 16F877, you could also try testing it with that PIC. |
|
|
newpic
Joined: 09 Aug 2005 Posts: 32
|
|
Posted: Fri Jun 10, 2011 7:57 am |
|
|
I have Quote: | CCS PCM C Compiler, Version 3.249, 34474 |
using PIC16F877 and Pic demo 2 plus (old version as you have)I cut and paste your test code above. I build it and program it into board.
I got the following when key pressed:
key pressed ---------- hyperterminal
1 ----------------------- 0 * #
2 ----------------------- nothing
3 ----------------------- nothing
4 ----------------------- nothing
5 ----------------------- 1
6 ----------------------- 2
7 ----------------------- nothing
8 ----------------------- 4
9 ----------------------- 5
* ----------------------- nothing
0 ----------------------- 7
# ---------------------- 8 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 10, 2011 11:56 am |
|
|
Check your connections. Just by flipping around the connectors
and moving them "off" by 1 pin, I was able to get some strange effects.
The GH5001 data sheet shows the pin numbering system for the keypad.
Look on page 1, at the middle diagram (called Standard Versions). Look
at the pinout given at the bottom. That's the back side of the keypad.
http://media.digikey.com/pdf/Data%20Sheets/Grayhill%20PDFs/96%20Series.pdf
It looks like this:
Code: |
-------------------
| 7 6 5 4 3 2 1 |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------- |
Connections between PIC and keypad:
Code: |
Keypad PortB
1.......B1
2.......B2
3.......B3
4.......B4
5.......B5
6.......B6
7.......B7
|
Note there is no connection to Pin B0 on PortB. |
|
|
|
|
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
|