CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Keypad and LCD

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

Keypad and LCD
PostPosted: Fri Feb 08, 2008 6:42 pm     Reply with quote

Please could someone help me with the kbd.c, lcd.c and lcdkb drivers.
I have read numerous posts about this subject but still cannot get the keyboard to scan/work.

Prerequisites:
PIC18F4525
2x3 bespoke keypad (2 cols, 3 rows)
using picdem 2 plus
tried with and without 10k pull ups on the rows - (because of the weak pull ups). None on the columns.
The LCD works fine and displays with other programs.

my main code is:
Code:
#include <18F4525>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)

#include lcd.c   //this is in the correct brackets but just doesn't show
#include kbd.c  //this is in the correct brackets but just doesn't show


void main() {
   char k;
   port_b_pullups(TRUE);
   kbd_init();
   lcd_init();
 

   lcd_putc("\fReady...\n");

   while (TRUE) {
      k=kbd_getc();
      if(k!='0')
   
      if(k=='1')
         lcd_putc("\1\n");

      if(k=='2')
         lcd_putc("\2\n");

      if(k=='3')
         lcd_putc("\3\n");

      if(k=='4')
         lcd_putc("\4\n");

      if(k=='5')
         lcd_putc("\5\n");

      if(k=='6')
         lcd_putc("\6\n");
   }
}

My kbd.c code has been changed for the following pin configs:
Code:
#define row0 PIN_B5
#define row1 PIN_B6
#define row2 PIN_B7
#define col0 PIN_B3
#define col1 PIN_B4
#define ALL_ROWS (ROW0|ROW1|ROW2)
#define ALL_PINS (ALL_ROWS|COL0|COL1)
// Keypad layout:
char const KEYS[3][2] =
{{'1','2'},
 {'3','4'},
 {'5','6'}};


The full kbd.c is:

Code:
// 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:

//Keypad connection:
#define row0 PIN_B5
#define row1 PIN_B6
#define row2 PIN_B7
#define col0 PIN_B3
#define col1 PIN_B4


#define ALL_ROWS (ROW0|ROW1|ROW2)
#define ALL_PINS (ALL_ROWS|COL0|COL1)

// Keypad layout:
char const KEYS[3][2] =
{{'1','2'},
 {'3','4'},
 {'5','6'}};

#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;
     
       }

       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;
             last_key =KEYS[row][col];
             kbd_down = TRUE;
          } else {
             ++col;
             if(col==2)
               col=0;
          }
       }
      kbd_call_count=0;
   }
  set_tris_kbd(ALL_PINS);
  return(kchar);
}


It compiles fine and just displays ready on the LCD. Testing with a meter I cannot see any voltage change on the column pins - as it cycles through to detect a buttton press.

Any help would be upmost appreciated as this is really annoying me now.


Carl
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Feb 08, 2008 7:29 pm     Reply with quote

Quote:
while (TRUE) {
k=kbd_getc();
if(k != '0')

if(k=='1')
lcd_putc("\1\n");

if(k=='2')
lcd_putc("\2\n");

if(k=='3')
lcd_putc("\3\n");

if(k=='4')
lcd_putc("\4\n");

if(k=='5')
lcd_putc("\5\n");

if(k=='6')
lcd_putc("\6\n");
}
}

In the code above, you are testing k against a value of '0'. What's the
hex value of a zero inside single-quotes ? Look at the CCS sample
program, ex_lcdkb.c. It's also doing a test of the k variable. What
value is it testing k against ? What should be done to fix that line in
your code ?

Also, you're testing k in an if() statement. Then you want to do six
other tests, provided that k is non-zero. You are missing a pair
of braces.

Then finally, you are sending chars to the lcd in the six if() statements.
But all the chars have a slash in front of them. What does a slash do
to the value of a char ? What type of value is the LCD expecting, and
what are you actually sending to it ?
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Feb 09, 2008 2:45 am     Reply with quote

Thankyou for your assistance - much appreciated. I will go through all the points you have mentioned and reply back.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Feb 09, 2008 7:16 am     Reply with quote

changed the '0' to just 0 but made no difference so i thought i would just copy the lcdkb file with changes as shown:

#include <18F4525>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)

#include <lcd.c>
#include <kbd.c>


void main() {
char k;
port_b_pullups(TRUE);
lcd_init();
kbd_init();

lcd_putc("\fReady...\n");

while (TRUE) {
k=kbd_getc();
if(k!=0)
if(k=='*')
lcd_putc('\f');
else
lcd_putc(k);
}
}

It still didn't do anything apart from display Ready...
Can you explain what this means if(k=='*') - I cant find an explanation anywhere. Do I need to change it?

Because I'm using the weak pull_ups do I still need the 10k Pull ups on the rows?


Also when I plug in the IDC, the screen does not clear - even if I press erase target device. this is strange though, because every other program I have done, as soon as I plug in the IDC the LCD lights up every pixel like it should do?

It always compiles and I have made changes in all the three programs(lcd.c, kbd.c and lckbd.c) just to force a compile error and it does.

It cant be a problem with the LCD.
Maybe I have the keypad wrong? When I power down the PICDEM2 plus and then power up I measured the voltage on the column lines and they go from 0V to 5V when all six buttons are pressed and released . The voltage on the rows stays at 5V regardless because of the pullups.


When I program it and measure the voltages they are different.

Thankyou for any assistance you can give on this would be very much appreciated.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Feb 09, 2008 12:38 pm     Reply with quote

Code:

if(k=='*')
   lcd_putc('\f');

If the star key (asterisk) is pressed, the PIC will send '\f' to the lcd.
To find the meaning of the lcd commands, look at the comments at
the start of the LCD.c file. Here is the directory for that file:
Quote:
c:\Program Files\Picc\Drivers\lcd.c


Also:
Post the manufacturer and part number of the keypad. Post a link
to the web page for the keypad. If you don't know that information
because the keypad came already installed on a development board,
then post the manufacturer, part number, and web page of the board.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Feb 09, 2008 1:05 pm     Reply with quote

I have made a keypad by rewiring two individual 1x3 pads.
Part Number: MCAK103BSSSWPMM

It is a bank of three pushbuttons (times 2=6 buttons in total) soldered together in the conventional way:

Keypad1 Keypad2
row1 (wired to) row1 >B6 via 10k pullup
row2 (wired to) row2 >B7 via 10k pullup
row3 (wired to) row3 >B8 via 10k pullup
Col0 (not wired to Col1) >B4 No resistor
(not wired to Col0) Col1 >B5 No resistor


Therefore I do not have a '*'
I understand that the '*' is on normal keypads and when pressed it will display the next command as you have shown. obviously this can be used with all the other pads on the keypad like '1', '2' etc. I have tried these different pad variables but it still doesn't work.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Feb 09, 2008 4:00 pm     Reply with quote

Here is the web page for the keypad. The link for the data sheet is
in the lower left corner. It's just three switches with one column pin
and 3 row pins on the connector.
http://uk.farnell.com/jsp/search/productdetail.jsp?sku=1182229&N=401
I can't work on this anymore today, but I can work on it Sunday.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Feb 09, 2008 4:07 pm     Reply with quote

I already had the datasheet.
Sorry I should have said. Its the fact that its not working is the problem.

I would be extremely grateful if you could help me tomorrow.

Thanks for your help

Carl
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Feb 10, 2008 2:52 pm     Reply with quote

Quote:

#define row0 PIN_B5
#define row1 PIN_B6
#define row2 PIN_B7
#define col0 PIN_B3
#define col1 PIN_B4

Keypad1 Keypad2
row1 (wired to) row1 >B6 via 10k pullup
row2 (wired to) row2 >B7 via 10k pullup
row3 (wired to) row3 >B8 via 10k pullup
Col0 (not wired to Col1) >B4 No resistor
(not wired to Col0) Col1 >B5 No resistor

I'm starting to work on this, and I noticed an inconsistency.
You have two different sets of definitions in your posts shown above.
There are different pin numbers in each set. Also, the 2nd set
refers to a pin B8, which doesn't exist on an 18F4525.

Can you post a revised list of the wire connections between
the two keypads and the PIC ?

The keypad data sheet shows that the pinout is as follows:
Code:

Row1 Row2 Row3 Column
 o    o    o    o

This is with the keypad oriented as shown in the photo on the data sheet.
Guest








PostPosted: Mon Feb 11, 2008 1:30 pm     Reply with quote

sorry i have miss-typed. the original is correct as code:
#define row0 PIN_B5
#define row1 PIN_B6
#define row2 PIN_B7
#define col0 PIN_B3
#define col1 PIN_B4
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Mon Feb 11, 2008 1:35 pm     Reply with quote

so the way I have it set up is code:

Keypad1 Keypad2
row0(wired to) row0 >B5 via 10k pullup
row1 (wired to) row1 >B6 via 10k pullup
row2 (wired to) row2 >B7via 10k pullup
Col0 (not wired to Col1) >B3 No resistor
(not wired to Col0) Col1 >B4 No resistor
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Mon Feb 11, 2008 4:50 pm     Reply with quote

PROBLEM SOLVED.

it was the code in the end I did not have it configured correctly. Here is the code I use with LCD.C, KBD.C and LCDKB.C.

I am using this code with the PICDEM2 PLUS Board (v2002)

So LCD.C:
Code:
Code:
// As defined in the following structure the pin connection is as follows:
// D0 D8
// D1 D9
// D2 D10
// D3 D11
// D4 RS
// D5 RW
// D6 E
// LCD pins D4-D7 are not used

#use delay (clock=4000000)
// This structure is overlayed onto the data ports so that you may use
// whatever ports you desire
struct lcd_pin_map
{
boolean dummy; // PinA0 is not used
boolean enable; // PinA1
boolean rw; // PinA2
boolean rs; // PinA3
int unusedA : 4; // The rest of portA
int unusedB; // portB is not used
int unusedC; // portC is not used
int data : 4; // lower nibble of portD is used for data lines
int unusedD : 4; // The rest of portD
} lcd;
#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif

struct lcd_tris_map
{
boolean dummy; // PinA0 is not used
int control : 3;
int unusedA : 4; // The rest of portA
int unusedB; // portB is not used
int unusedC; // portC is not used
int data : 4; // lower nibble of portD is used for data lines
int unusedD : 4; // The rest of portD
} lcdtris;

#if defined(__PCH__)
#locate lcdtris = 0xF92
#else
#locate lcdtris = 0x85
#endif

#define set_tris_lcd(x) lcdtris.data = (x); lcdtris.control = 0;



#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line


byte CONST LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.


// The following are used for setting
// the I/O port direction register.

#define LCD_WRITE 0 // For write mode all pins are out
#define LCD_READ 15 // For read mode data pins are in


//--------------- Start of code ---------------------------------





byte lcd_read_byte() {
byte low,high;

set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4>> 4);
lcd_send_nibble(n & 0xf);
}


void lcd_init() {
byte i;

set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( byte x, byte y) {
byte address;

if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1); break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}

char lcd_getc( byte x, byte y) {
char value;

lcd_gotoxy(x,y);
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}

KBD.c:

Code:

Code:
//Keypad connection:
#define row0 PIN_B5
#define row1 PIN_B6
#define row2 PIN_B7
#define col0 PIN_B3
#define col1 PIN_B4

// Keypad layout:
char const KEYS[3][2] =
{{'1','2'},
{'3','4'},
{'5','6'}};

#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))
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);
break;

case 1:
output_high(col0);
output_low(col1);
break;

case 2:
output_high(col0);
output_high(col1);
break;

case 3:
output_low(col0);
output_low(col1);
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;

last_key =KEYS[row][col];
kbd_down = true;
}
else
{
++col;
if(col==2)
col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}



LCBKD.C:
Code:
Code:
#include <18F4525.h>
#include
#include
#fuses EC_IO,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)

void main() {
char k;
port_b_pullups(TRUE);
lcd_init();
kbd_init();

lcd_putc("\fReady...\n");

while (TRUE) {
k=kbd_getc();
if(k!=0)
if(k=='1')
lcd_putc('\f');
else
lcd_putc(k);
}
}

It all works fully -and I am very happy. THankyou for your assistance PCM Programmer.
Code:
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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