|
|
View previous topic :: View next topic |
Author |
Message |
zogbog
Joined: 02 Jun 2004 Posts: 16
|
Keypad And LCD So Far........ |
Posted: Fri Jul 09, 2004 3:12 pm |
|
|
First of all thanks to everyone who has helped me over the past few weeks.
I am using a 16F877 to drive a keypad and an LCD. the drivers that i am using are lcd.c and kbd.c I have had great success in driving both the LCD and the keypad on port b. However i really need to drive them off port d freeing up port b for other things.
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 //THIS COMENTED OUT
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);
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
//***end of lcd.c**//
kbd.c
// Un-comment the following define to use port B
//#define use_portb_kbd TRUE //THIS COMENTED OUT
// 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);
}
//**end of kbd.c**//
MAIN PROGRAM
#if defined(__PCB__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=4000000)
#elif defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=4000000)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOPROTECT
#use delay(clock=4000000)
#endif
//#define use_portb_kbd True //THIS COMENTED OUT
#include <lcd.c>
#include <kbd.c>
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);
}
}
|
these are the CCS drivers/examples and as far as i can tell i have commented out in all the right places??? Ihave also tried 10K pull ups on the colomn lines but no joy. The lcd driver works fine on port d and b but the keypad will only work on port b and not on port d (with or without the lcd in parallel.). As i am new to the programming side of things am i missing something in the cinfig of port d???
Any help is as always much appreciated |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 09, 2004 10:31 pm |
|
|
Quote: | I have also tried 10K pull ups on the column lines but no joy. |
Add pullups to the Row pins on Port D. |
|
|
zogbog
Joined: 02 Jun 2004 Posts: 16
|
Keypad And LCD So Far........ |
Posted: Mon Jul 12, 2004 2:18 pm |
|
|
great stuff it works! i now have the keypad and the lcd working on port d on a pic dem 2+ board. i will tidy up my code and post it for anyone else who may be in the same position as me. Once again thanks for all the help
|
|
|
treitmey
Joined: 23 Jan 2004 Posts: 1094 Location: Appleton,WI USA
|
|
|
cxiong
Joined: 09 Sep 2003 Posts: 52
|
|
Posted: Wed Aug 25, 2004 12:26 pm |
|
|
I use the exact code you post in here on my PIC DEMO 2 Plus and I always have the " Ready...! " message display on the LCD and when I press any key on the key pad, it does nothing more.
I have the black 4X3 keypad.
Here is my connection
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 25, 2004 12:48 pm |
|
|
Get rid of those pull-down resistors and enable the Port B pull-ups.
Use this CCS function to do that:
port_b_pullups(TRUE); |
|
|
|
|
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
|