|
|
View previous topic :: View next topic |
Author |
Message |
zogbog
Joined: 02 Jun 2004 Posts: 16
|
LCD And Keypad Basics Gone Wrong |
Posted: Fri Apr 21, 2006 1:28 pm |
|
|
I am trying to run a 4X3 keypad and 16X2 LCD off port D on a PIC16F877. I am using the CCS LCD.C and KBD.C drivers. My pinout is as follows
PIC----LCD---KBD
D0-----EN----NC
D1-----RS----R1-----10K Pullup
D2-----RW----R2-----10K Pullup
D3-----NC----R3-----10K Pullup
D4-----D4----R4-----10K Pullup
D5-----D5----C1
D6-----D6----C2
D7-----D7----C3
NC=N0 connection.
When the pullup resistors are in place nothing happens.
When the pullup resistors are removed the LCD says "Ready..."
below is the code that i am using both drivers and main. I have had this working once upon a time but i cant find my example and it has got me stumped. I seem to recall there being resistors or diode between the keypad and lcd but i could be mistaken. Heres the code
Code: |
***********Lcd.c***************
// As defined in the following structure the pin connection is as follows:
// D0 enable
// D1 rs
// D2 rw
// D4 D4
// D5 D5
// D6 D6
// D7 D7
//
// LCD pins D0-D3 are not used and PIC D3 is not used.
// Un-comment the following define to use port B
// #define use_portb_lcd TRUE
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;
#if defined(__PCH__)
#if defined use_portb_lcd
#byte lcd = 0xF81 // This puts the entire structure
#else
#byte lcd = 0xF83 // This puts the entire structure
#endif
#else
#if defined use_portb_lcd
#byte lcd = 6 // on to port B (at address 6)
#else
#byte lcd = 8 // on to port D (at address 8)
#endif
#endif
#if defined use_portb_lcd
#define set_tris_lcd(x) set_tris_b(x)
#else
#define set_tris_lcd(x) set_tris_d(x)
#endif
#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.
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 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) | 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_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);
delay_ms(2);
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);
while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
***********Lcd.c***************
|
Code: |
***********Kbd.c***************
//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);
}
***********Kbd.c***************
|
Code: |
***********EX_LcdKb.c***************
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#include <lcd.c>
#include <kbd.c>
void main() {
char k;
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);
}
}
|
If anyone can see where i have gone wrong or if anyone has any clues to point me in the right direction as always it is greatly appreciated.
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 21, 2006 1:44 pm |
|
|
It looks similar to what I'm doing in this thread, except that
you're using Port D instead of Port B. So it should work.
http://www.ccsinfo.com/forum/viewtopic.php?t=26229
1. What happens if you disconnect the keypad and its cable
from the board ? Does the LCD display "Ready" then ?
If so, there maybe a defect in the keypad or cable.
2. What happens if you comment out the init_kbd() line ?
Basically, I'm trying to see if the keypad is the problem. |
|
|
zogbog
Joined: 02 Jun 2004 Posts: 16
|
Keypad And LCD |
Posted: Fri Apr 21, 2006 2:09 pm |
|
|
I am simulating the software on proteus. I get the same effect on port b.
I have had the code working on the PICDEM2+ dev board with the changed LCD.C for that board and i have had it working on both port b and d in proteus before but for some reason now i cant figure it out. I noticed in your thread you changed the fuse from HS to XT to account for the 4MHz crystal so i wil check my clock speeds are correct and try again.
thanks |
|
|
zogbog
Joined: 02 Jun 2004 Posts: 16
|
Port D LCD And Keypad |
Posted: Mon Apr 24, 2006 12:20 pm |
|
|
So far i have managed to simulate
1)The Keypad on PORT D and the LCD on PORT B
2)The Keypad on PORT B and the LCD on PORT D
3)The Keypad and the LCD in parallel on PORT B.
But when i put both in parrallel on PORT D the LCD is blank.
If i remove the pullup resistors the LCD displays "Ready..." but the keypad is dead.
The circuits are exactly the same as when I have had success on PORT B but parallel on PORT D no joy.
I am sure its not the drivers because they work but iIthink there is something missing from the circuit.
Maybe some resistors or diodes between the LCD and the keypad?... If anyone has had any success with this circuit on port D the please could you help me.
Thanks
[/img] |
|
|
zogbog
Joined: 02 Jun 2004 Posts: 16
|
|
Posted: Mon Apr 24, 2006 12:59 pm |
|
|
Here is a link to the circuit diagram
[img]http://homepage.mac.com/damienpattrick/.Public/CCSDEMOPORTD.BMP[/img] |
|
|
|
|
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
|