Interface to a Serial LCD
Here is a library to interface your PIC code to an LCD that is
controlled via a serial line. One such LCD is available from Scott Edwards
Electronics. There are many others, and the code
shown here can easily be adpated to other LCD displays by
changing some defines.
LCD Library Source Code
Here is my library source code. Or you
can download all the files referenced on
this page (a gzip'd tar file). For DOS/Windows users, you can download
LCDlib.zip in ZIP format.
The following routines are defined:
- void lcd_putc(char c) send the byte c to the LCD
- void lcd_clear(void) clears the LCD screen
- void lcd_home(void) homes the LCD cursor
- void lcd_puts() print a string **UNIMPLEMENTED**
- void lcd_printhex(char c) prints byte c as a 2 digit hex character
- void lcd_printdec(char c) prints byte c as a decimal digit string
- void lcd_printbin(char c) prints byte c as a binary string
- void lcd_scroll_left(char n) scrolls LCD screen left n positions
- void lcd_scroll_right(char n) scrolls LCD screen right n positions
- void lcd_goto(char row, char col) goto a location
I'll describe each routines briefly, but they are very simple to
understand.
void lcd_putc(char c) - send a byte to the LCD
This routine is the heart of the LCD library: it will send a byte
specified in the argument c to the LCD connected to the
port defined by LCDPORT and pin LCDPIN. All the other
routines use this code.
lcd_putc() assumes that the LCD is running at 9600 baud, 8-N-1 serial
settings. If your LCD is running at a different baud
rate, or you have a faster PIC, you will have to
adjust the timing loop starting at lcdtxloop.
The lcd_putc() routine places a 10ms pacing delay between each
character.
void lcd_clear(void) - clear the LCD screen
Building upon the lcd_putc() routine is easy, as this routine
shows. We simply send the byte sequence that clears
the display.
void lcd_home(void) - home the LCD cursor
Sends the byte sequence that homes the LCD cursor to the top left hand
corner.
void lcd_puts() - print a string **UNIMPLEMENTED**
This function will print a string on the display. Unfortunately, the
C2C compiler currently does not support
pointers, so there is no easy way to write this
code. I'm working on this...
void lcd_printhex(char c) - print byte as hex
Print a byte value on the display as 2 hex characters. For example,
the value 255 would be printed as FF. The code
prints the hi nibble first (the upper 4 bits of
the byte), followed by the lower nibble.
void lcd_printdec(char c) - print byte as decimal
Print a byte value as a decimal string. For example, the value 123 is
printed as the characters "123". This function
performs repeated subtractions: starting at 100,
we subtract until the value left is less than
100. We then repeat the loop for 10's. Whatever
is left is the units value. Effectively, this
routine performs division by repeated
subtraction.
The output of lcd_printdec() is always 3 digits long: 001 as against
just 1.
void lcd_printbin(char c) - print byte as binary
This routine prints a binary representation of a byte. For example,
129 would be printed as 10000001. 8 bits are
always printed, which means that the value may
have leading zeros: 5 would be printed as
00000101.
void lcd_scroll_left(char n) - scroll screen left
Scroll the LCD display left n positions. The effect of this command
depends a lot on the type of LCD display you
have.
void lcd_scroll_right(char n) - scroll screen right
Scroll the LCD display right n positions. The effect of this command
depends a lot on the type of LCD display you
have.
void lcd_goto(char row, char col) - goto a position
Positions the cursor at the specified row and column. The row argument
starts at 0. So the first line on a two line
LCD is row 0, and the second line is row
1. Similarly, the col argument starts at 0.
If you print off the screen, it is not displayed, but is stored in
the LCD's RAM. Use the lcd_scroll_left and lcd_scroll_right commands
to access the data.
Examples of how to use the library
Here is some sample code using the LCD library. A schematic for wiring
this up looks as follows:
The Makefile for this library is as follows:
#
# Makefile for LCD test code
#
# Mark Crosbie 9/15/98
#
LIBS=lcd.lib
ASMINCS= p16c84.inc
C2CINCS=
all: lcdtest1.hex lcdtest2.hex lcdtest3.hex
lcdtest1.hex: lcdtest1.asm
gpasm -r dec -p 16c84 -t lcdtest1.asm
lcdtest1.asm: lcdtest1.c lcd.lib delays.lib
c2c ${C2CINCS} -olcdtest1.asm lcd.lib delays.lib lcdtest1.c
lcdtest2.hex: lcdtest2.asm
gpasm -r dec -p 16c84 -t lcdtest2.asm
lcdtest2.asm: lcdtest2.c lcd.lib delays.lib
c2c ${C2CINCS} -olcdtest2.asm lcd.lib delays.lib lcdtest2.c
lcdtest3.hex: lcdtest3.asm
gpasm -r dec -p 16c84 -t lcdtest3.asm
lcdtest3.asm: lcdtest3.c lcd.lib delays.lib
c2c ${C2CINCS} -olcdtest3.asm lcd.lib delays.lib lcdtest3.c
lcdtest4.hex: lcdtest4.asm
gpasm -r dec -p 16c84 -t lcdtest4.asm
lcdtest4.asm: lcdtest4.c lcd.lib delays.lib
c2c ${C2CINCS} -olcdtest4.asm lcd.lib delays.lib lcdtest4.c
lcd.lib: lcd.c
c2c ${C2CINCS} -lib -olcd.lib lcd.c
delays.lib: delays.c
c2c ${C2CINCS} -lib -odelays.lib delays.c
clean:
rm *.hex *.lib core *.asm *.lst
Example 1 - Printing numbers
The source code for this test case is
available. This test prints the numbers
between 32 and 128 as an ASCII
character, a decimal number and a hex number. There is a 1 second
delay each time through the loop so you can see the output. The code
is quite simple: first the PORTA pin to which the LCD is connected is
set to be an output. The code then delays for a second to give the LCD
a chance to initialize (it really only needs a few 100
milliseconds). Then the LCD is cleared using lcd_clear().
The loop iterates through the ASCII characters between 32 and 128 and
prints each one as a character, a decimal value and a hex value.
The hex output file is available for a PIC
16C84.
/*
* lcdtest1.c
*
* Test lcd.lib and delays.lib
*
* Shows the operation of lcd_putc, lcd_printdec and lcd_printhex
*
* Connect the LCD to port A pin 1 (i.e. physical pin 18 on a 16C84)
*
* Mark Crosbie 9/15/98
*/
#define LCDPIN 1
void main(void) {
char i;
set_bit(STATUS, RP0); /* select the register bank 1 */
clear_bit(TRISA, LCDPIN); /* Port A is output */
clear_bit(STATUS, RP0);
delay_s(1);
lcd_clear();
delay_s(1);
while(1) {
for(i=32; i < 128; i++) {
lcd_putc(i);
lcd_putc(' ');
lcd_printdec(i);
lcd_putc(' ');
lcd_printhex(i);
delay_s(1);
lcd_clear();
}
}
}
Example 2 - Printing at a location
This example shows how to position the cursor at a specific location
and print information. The source code is
available. It uses the previous example's loop and adds
lcd_goto() calls between each print.
The assembly output is available, as is the
hex output file for a PIC
16C84.
/*
* lcdtest2.c
*
* Test lcd.lib and delays.lib
*
* Shows the operation of lcd_goto to position cursor
*
* Connect the LCD to port A pin 1 (i.e. physical pin 18 on a 16C84)
*
* Mark Crosbie 9/20/98
*/
#define LCDPIN 1
void main(void) {
char i;
set_bit(STATUS, RP0); // select the register bank 1
clear_bit(TRISA, LCDPIN); // Port A is output
clear_bit(STATUS, RP0);
delay_s(1);
lcd_clear();
delay_s(1);
while(1) {
for(i=32; i < 128; i++) {
lcd_putc(i);
lcd_goto(0,5);
lcd_printdec(i);
lcd_goto(0,10);
lcd_printhex(i);
lcd_goto(1,2); /* goto row 1 col 5 */
lcd_printbin(i);
delay_s(1);
lcd_clear();
}
}
}
Example 3 - Scrolling the LCD
We now test the scrolling commands to scroll the LCD left and
right. My LCD can only display 16 columns of text, but if you continue
to print, the extra characters are still stored in the LCD's RAM, but
are not displayed. However, if you scroll the LCD left you can display
the characters off the screen.
This simple example prints 32 characters to the first row on the
LCD. It then scrolls the LCD left a character at a time, and then
right a character at a time.
The source code is available, as is the generated assembly output and the hex output file.
/*
* lcdtest3.c
*
* Test lcd.lib and delays.lib
*
* Shows the operation of lcd_scroll_left and lcd_scroll_right
* commands
*
* Prints out the first 32 characters of the ASCII character set. Only
* the first 16 show on my LCD, so I scroll left by 16
* characters. Then I scroll back right by 16 characters.
*
* Connect the LCD to port A pin 1 (i.e. physical pin 18 on a 16C84)
*
* Mark Crosbie 9/20/98
*/
#define LCDPIN 1
void main(void) {
char i;
set_bit(STATUS, RP0); // select the register bank 1
clear_bit(TRISA, LCDPIN); // Port A is output
clear_bit(STATUS, RP0);
delay_s(1);
lcd_clear();
delay_s(1);
while(1) {
for(i=32; i < 64; i++) {
lcd_putc(i);
}
delay_s(1);
for(i=0; i < 16; i++) {
lcd_scroll_left(1);
delay_ms(200);
}
delay_s(2);
for(i=0; i < 16; i++) {
lcd_scroll_right(1);
delay_ms(200);
}
delay_s(2);
lcd_clear();
}
}
[BACK] to the PIC page.
[HOME] to Mark's page.
Last modified on Dec 1, 1998 by
Mark Crosbie (mcrosbie@best.com)