View previous topic :: View next topic |
Author |
Message |
crushneck
Joined: 27 Nov 2005 Posts: 29
|
How to program Keypad |
Posted: Thu Dec 22, 2005 1:19 am |
|
|
How to program a 4x3 keypad and get and output from LCD...?
Im using a PIC16F877 and using PORT b for keypad and port D for LCD... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 22, 2005 1:32 am |
|
|
Look at these CCS example and driver files:
EX_LCDKB.C
KBD.C
LCD.C
These files are in:
c:\Program Files\Picc\Examples
and
c:\Program Files\Picc\Drivers |
|
|
crushneck
Joined: 27 Nov 2005 Posts: 29
|
Which pins?? |
Posted: Thu Dec 22, 2005 3:07 am |
|
|
i still have some question for the conection to port B..i didnt know which pin to which pin...maybe u can take a look at my keypad schematic diagram..its at the page 4 of 4...Components layout...12 keys - Connector
Maybe u can help me more...thanks
http://www.farnell.com/datasheets/26652.pdf |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Dec 22, 2005 11:07 am |
|
|
#define COL0 (1 << 2)
This would be on B2 or D2
#define COL1 (1 << 3)
This would be on B3 or D3
#define COL2 (1 << 6)
This would be on B6 or D6
You should be able to figure out the rest.
Make sure you pay attention to the #ifdef's to know what code is actually being used. The code will behave differently depending on what is #define'd |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 22, 2005 11:40 am |
|
|
Here is a table that shows the connections you must make
between your keypad connector pins and Port B on the PIC:
Code: |
Keypad Port
pin pin
X3 ------ B7
X2 ------ B6
X1 ------ B5
Y4 ------ B4
Y3 ------ B3
Y2 ------ B2
Y1 ------ B1
|
Other required changes:
1. Edit the KBD.C file and un-comment the following line:
// #define use_portb_kbd TRUE
so it looks like this:
Code: | #define use_portb_kbd TRUE |
2. Edit the EX_LCDKB.C file, and add a line to enable Port B pullups.
Add the line shown in bold below:
Quote: | 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);
}
} |
|
|
|
crushneck
Joined: 27 Nov 2005 Posts: 29
|
|
Posted: Fri Dec 23, 2005 2:11 am |
|
|
Yeah it works!!thanks ...but 1 more thing...
The numbers/letter apeared in the LCD...but it always overwrite each other....i want it to apear beside each other whenever a key is pressed |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 23, 2005 12:08 pm |
|
|
Quote: | The numbers/letter apeared in the LCD...but it always overwrite
each other....i want it to apear beside each other whenever a key is pressed |
Go to this website
http://www.geocities.com/dinceraydin/lcd/commands.htm
Scroll down to the section on:
Entry mode set command 06h
He has an animated display that shows how the LCD should look when
you initialize it with the 0x06 command.
In the CCS driver file, LCD.C, there is an array with the initialization
commands. Notice that the last byte is 6.
Code: | BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; | So if you used the CCS driver, your LCD should be initialized correctly.
Did you change the values in that array ?
------------
Another reason for your problem could be that you are clearing the
LCD screen after each character. The LCD is cleared by sending
the '\f' character (same as 0x0C) to the lcd_putc() function. Example:
lcd_putc('\f');
Are you clearing the screen after sending each character ?
If so, don't do that. |
|
|
crushneck
Joined: 27 Nov 2005 Posts: 29
|
|
Posted: Mon Dec 26, 2005 7:36 pm |
|
|
yes im using the character /f...but other than clearing the
LCD screen after each character,what other kind of character must i use??
Heres my main source code which contain the characters:
Code: | #include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS) //pin25=c6, pin26=c7
#include <lCD420.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*\n");
if(k=='#')
lcd_putc("\f#\n");
if(k=='0')
lcd_putc("\f0123456789012345678901234567890\n");
if(k=='1')
lcd_putc("\f1\n");
if(k=='2')
lcd_putc("\f2\n");
if(k=='3')
lcd_putc("\f3\n");
if(k=='4')
lcd_putc("\f4\n");
if(k=='5')
lcd_putc("\f5\n");
if(k=='6')
lcd_putc("\f6\n");
if(k=='7')
lcd_putc("\f7\n");
if(k=='8')
lcd_putc("\f8\n");
if(k=='9')
lcd_putc("\f9\n");
}
} |
And heres my LCD420 code
Code: | struct lcd_pin_map {
BOOLEAN rs; // Pin D0
BOOLEAN enable; // Pin D1
BOOLEAN rw; // Pin D2
BOOLEAN unused;
int data : 4; // Pins D4-D7
} lcd;
#byte lcd = 8 // This puts the entire structure
// on to port D (at address 8)
#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_d(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_d(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_d(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);
} |
I hope u can help....thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 26, 2005 7:50 pm |
|
|
Quote: | The numbers/letter apeared in the LCD...but it always overwrite each other.
|
Quote: |
while (TRUE) {
k=kbd_getc();
if(k!=0)
if(k=='*')
lcd_putc("\f*\n");
if(k=='#')
lcd_putc("\f#\n");
if(k=='0')
lcd_putc("\f0123456789012345678901234567890\n");
if(k=='1')
lcd_putc("\f1\n"); |
What's wrong with using the code in the CCS example ?
It does not do the '\f' before each character.
You should use the example code:
Code: | 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);
}
} |
|
|
|
crushneck
Joined: 27 Nov 2005 Posts: 29
|
|
Posted: Mon Dec 26, 2005 9:07 pm |
|
|
ok ive changed the code...it works well...thanks...
i have a question...im using an analog input at port RA0...so can i get the input of the analog in my LCD?....like example how many voltage,temperature,any value from the input of the analog... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 26, 2005 10:41 pm |
|
|
This program will display the A/D value in the upper left corner of the LCD.
Code: |
#include <16F877.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#include <lcd.c>
//===============================
void main()
{
int16 result;
lcd_init();
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
while(1)
{
result = read_adc();
lcd_gotoxy(1,1);
printf(lcd_putc, "%04LX", result);
delay_ms(100);
}
} |
|
|
|
crushneck
Joined: 27 Nov 2005 Posts: 29
|
|
Posted: Wed Dec 28, 2005 7:51 pm |
|
|
thanks for the codes...it works fine now..thanks alot... |
|
|
crushneck
Joined: 27 Nov 2005 Posts: 29
|
Upgrade to PIC18F452 |
Posted: Wed Feb 01, 2006 10:07 am |
|
|
I decided to upgrade my PIC to PIC18F452 but then my circuit did not work...what need to be done to my code for it to work??
Code: | #include <18F452.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)
#include <lcd.c>
//===============================
void main()
{
int16 result;
lcd_init();
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
while(1)
{
result = read_adc();
lcd_gotoxy(1,1);
printf(lcd_putc, "%04LX", result);
delay_ms(100);
}
} |
|
|
|
|