|
|
View previous topic :: View next topic |
Author |
Message |
eiji
Joined: 03 Sep 2008 Posts: 9
|
problem : 4x4 keypad & 4x20 lcd |
Posted: Thu Sep 04, 2008 1:13 am |
|
|
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.
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
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
|
|
Posted: Thu Sep 04, 2008 1:18 am |
|
|
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
|
|
Posted: Thu Sep 04, 2008 1:34 am |
|
|
Sorry i forgot to include that. I've edited my post.thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Sep 04, 2008 1:53 am |
|
|
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
|
|
Posted: Thu Sep 04, 2008 2:02 am |
|
|
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
|
|
Posted: Fri Sep 05, 2008 9:27 am |
|
|
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 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
|
|
Posted: Sun Sep 21, 2008 7:57 pm |
|
|
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 |
|
|
eiji
Joined: 03 Sep 2008 Posts: 9
|
|
Posted: Sun Oct 19, 2008 12:17 pm |
|
|
could any genius help me? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 19, 2008 12:26 pm |
|
|
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
|
|
Posted: Sun Oct 19, 2008 11:46 pm |
|
|
Thanks for the comment
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 |
|
|
eiji
Joined: 03 Sep 2008 Posts: 9
|
|
Posted: Mon Oct 20, 2008 4:47 am |
|
|
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
|
|
Posted: Mon Oct 20, 2008 8:27 am |
|
|
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
|
|
Posted: Sun Dec 09, 2012 10:01 am |
|
|
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++;
} |
|
|
|
|
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
|