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 support@ccsinfo.com

problem : 4x4 keypad & 4x20 lcd

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



Joined: 03 Sep 2008
Posts: 9

View user's profile Send private message

problem : 4x4 keypad & 4x20 lcd
PostPosted: Thu Sep 04, 2008 1:13 am     Reply with quote

Hello everyone. Could anyone help me solving my 4x4 keypad problem please? I'm using portB for the 4x20 lcd and portC and D for the 4x4 keypad. I think all the connections are right, with the 10K pullup resistor on the row pins.

The problem is, only a few buttons on the LCD can print the numbers when it's pressed, but those numbers printed on the LCD were random, sometimes its overflow the screen with random numbers. Please help me and I'll be very thankful. Smile

This is my 4x20 driver (lcd420.c):
Code:
//Keypad connection:
//     B0  enable
//     B1  rs
//     B2  rw
//     B4  D4
//     B5  D5
//     B6  D6
//     B7  D7
//
//   LCD pins D0-D3 are not used and PIC B3 is not used.

struct lcd_pin_map {                 // This structure is overlayed
           BOOLEAN enable;           // on to an I/O port to gain
           BOOLEAN rs;               // access to the LCD pins.
           BOOLEAN rw;               // The bits are allocated from
           BOOLEAN unused;           // low order up.  ENABLE will
           int     data : 4;         // be pin B0.
        } lcd;

#byte lcd = 6                        // This puts the entire structure
                                     // on to port B (at address 6)

#define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines


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.

struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in


BYTE lcdline;

BYTE lcd_read_byte() {
      BYTE low,high;

      set_tris_b(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_b(LCD_WRITE);
      return( (high<<4) | low);
}


void lcd_send_nibble( BYTE n ) {
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}


void lcd_send_byte( BYTE address, BYTE n ) {

      lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}


void lcd_init() {
    BYTE i;

    set_tris_b(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;

   switch(y) {
     case 1 : address=0x80;break;
     case 2 : address=0xc0;break;
     case 3 : address=0x94;break;
     case 4 : address=0xd4;break;
   }
   address+=x-1;
   lcd_send_byte(0,address);
}

void lcd_putc( char c) {
   switch (c) {
     case '\f'   : lcd_send_byte(0,1);
                   lcdline=1;
                   delay_ms(2);
                                           break;
     case '\n'   : lcd_gotoxy(1,++lcdline);        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);
}


This is my 4x4 keypad driver (kbd44.c):
Code:
//Keypad connection:
#define ROW0 PIN_C4
#define ROW1 PIN_C5
#define ROW2 PIN_C6
#define ROW3 PIN_C7
#define COL0 PIN_D4
#define COL1 PIN_D5
#define COL2 PIN_D6
#define COL3 PIN_D7

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

void kbd_init()
{
}

short int ROW_HIGH()
{
if(input (ROW0) || input (ROW1) || input (ROW2) || input (ROW3))
   return (1);
else
   {
   return (0);
   }
}

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_high(col0);
         output_low(col1);
         output_low(col2);
         output_low(col3);
         break;
         
         case 1:
         output_low(col0);
         output_high(col1);
         output_low(col2);
         output_low(col3);
         break;
         
         case 2:
         output_low(col0);
         output_low(col1);
         output_high(col2);
         output_low(col3);
         break;

         case 3:
         output_low(col0);
         output_low(col1);
         output_low(col2);
         output_high(col3);
         break;
      }

   if(kbd_down)
   {
      if(!ROW_HIGH())
         {
            kbd_down=false;
            kchar=last_key;
            last_key='\0';
         }
   }
   else
   {
      if(ROW_HIGH())
      {
         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);
}


This is my program:
Code:
#include<16f877.h>
#fuses xt,noprotect,nowdt
#use delay(clock=4000000)
#include<lcd420.c>
#include<kbd44.c>


void main()
{
   char k=0;

   lcd_init();
   kbd_init();

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

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


Thanks again for those willing to help Smile


Last edited by eiji on Sun Oct 19, 2008 12:07 pm; edited 2 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 04, 2008 1:18 am     Reply with quote

Post a short program that uses these drivers. Post the #include,
#fuses, #use delay(), main(), all variables, etc. It should be a short
but complete program.
eiji



Joined: 03 Sep 2008
Posts: 9

View user's profile Send private message

PostPosted: Thu Sep 04, 2008 1:34 am     Reply with quote

Sorry i forgot to include that. I've edited my post.thanks Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 04, 2008 1:53 am     Reply with quote

Quote:
I think all the connections are right ,with the 10K pullup resistor on the row pins.


You have series resistors in your circuit, not pull-ups. Also, it looks like
they are on the column pins, not the row pins.

1. Get rid of the series resistors.

2. Add pull-up resistors on the row pins.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Sep 04, 2008 2:02 am     Reply with quote

Apart from the meaningful specific suggestions already placed, you may also consider this:

You have developed a complex (more than a few lines of code) application, download it to the processors and - it doesn't work. Very usual, I think. You can immediately ask for help or first try to understand which part of the code (or the hardware) isn't performing correct. This can't be done from the distance, but easily at your site. It's basically easy to determine, if the keyboard encoder or the LCD driver (or both at worst case) are faulty. At this point, you can either carry on in debugging or ask for effective help.
eiji



Joined: 03 Sep 2008
Posts: 9

View user's profile Send private message

PostPosted: Fri Sep 05, 2008 9:27 am     Reply with quote

PCM programmer wrote:

You have series resistors in your circuit, not pull-ups. Also, it looks like
they are on the column pins, not the row pins.

1. Get rid of the series resistors.

2. Add pull-up resistors on the row pins.


Thank u very much, i've done the modification and the circuit works well now Very Happy Now i can proceed to my password program. I'll post the program later.


Last edited by eiji on Sun Oct 19, 2008 12:09 pm; edited 1 time in total
eiji



Joined: 03 Sep 2008
Posts: 9

View user's profile Send private message

PostPosted: Sun Sep 21, 2008 7:57 pm     Reply with quote

Dear forumers, can anyone help in checking my program? It's seems the LCD just shown "WRONG PASSWORD", although the password entered is correct (1234). Below is the coding:

Code:
#include<16f877.h>
#fuses xt,noprotect,nowdt
#use delay(clock=4000000)
#include<string.h>
#include<lcd420.c>
#include<kbd4.c>

char k=0,string[5],password[5];
int i=0,j=0;

void main()
{
   lcd_init();
   kbd_init();

   while(1)
   {
    {
      lcd_putc("\fEnter Password:\n");
      i=1;

      while(i!=0)
      {
       k=kbd_getc();
       if(k!=0)
       {
         if(k=='D') // 'D' button represent 'ENTER' key
         {
          strcpy(password, "1234");
          if(strcmp(string, password)==0)
          {
           lcd_putc("\f\n   ACCESS GRANTED");
           delay_ms(3000);           
          }

          else
          {
           lcd_putc("\f\n   WRONG PASSWORD");
           delay_ms(3000);
          }
         
          i=0;
         }

         else
         {
          lcd_putc(k);
          for(j=1;j<5;j++)
          string[j]=k;
         }
       }
      }
    }
   }
}


Thanks in advance Smile
eiji



Joined: 03 Sep 2008
Posts: 9

View user's profile Send private message

PostPosted: Sun Oct 19, 2008 12:17 pm     Reply with quote

could any genius help me? Sad
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Oct 19, 2008 12:26 pm     Reply with quote

You're trying to design two things at one time:
1. Keypad input of sequential numbers into an array.
2. Compare the array to a password.

Don't design two things at one time. Get one of them working, then
do the other one.

Suggestion: Get item #1 working first. Remove all code that checks
for the password. Just take in characters, put each character into a
buffer as it is received, increment a pointer or an index for the buffer,
check the index to make sure you don't go past the end of the buffer,
and when you get the 'D' key, then display the contents of the buffer
to prove that it's working.
Guest








PostPosted: Sun Oct 19, 2008 11:46 pm     Reply with quote

Thanks for the comment Smile

I'm very beginner and I hope someone can helping better in the coding. But thanks for the suggestion, I'll try my best to figure out the solution Smile
eiji



Joined: 03 Sep 2008
Posts: 9

View user's profile Send private message

PostPosted: Mon Oct 20, 2008 4:47 am     Reply with quote

After doing some testing for a while, I think I found the problem:
Code:
if(strcmp(string, password)==0)    // this line never true because

string[j]=k                        // this line was compared with
strcpy(password, "1234");          // this line

But if I do it like this, It's work well:
Code:
strcpy(string, "1234");
strcpy(password, "1234");
if(strcmp(string, password)==0)    // this line will be executed

Although I managed to get string[1][2][3][4]=1234. Maybe it was memory problem. My question is, how to insert the string[j] into the strcpy,because from my observation this function only used constant value, like strcpy(string, ""1234"). Please correct me if I was wrong..
crystal_lattice



Joined: 13 Jun 2006
Posts: 164

View user's profile Send private message

PostPosted: Mon Oct 20, 2008 8:27 am     Reply with quote

When you copy the string using strcpy it terminates the string with a NULL character. The strcmp function will then fail when working with your custom string as it is not NULL terminated. RTFM for more info.
hunter007



Joined: 09 Dec 2012
Posts: 1
Location: Turkey

View user's profile Send private message AIM Address

PostPosted: Sun Dec 09, 2012 10:01 am     Reply with quote

eiji wrote:

else
{
lcd_putc(k);
for(j=1;j<5;j++)
string[j]=k;
}




change it like this..

int i=1,j=0
....

else
{
lcd_putc(k);
string[j]=k;
j++;

}
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