Stamp
This section follows the
standard Hitachi initialization
sequence to put the display
into eight-bit mode, using
multiple lines and the 5 x 7
font. It turns the underline
cursor off and causes the
cursor address pointer to
automatically increment after
a write or a read. Of course,
we’re not writing directly to the
LCD; we’re doing it through
the MCP23016 — so let’s have
a look at how that’s done:
Figure 2. Standard
Active-Low Button Circuit.
LCD_Command:
I2CIN SDA, Rd23016, GP1, [lcdCtrl]
lcdRS = 0
I2COUT SDA, Wr23016, GP1, [lcdCtrl]
LCD_Write:
I2COUT SDA, Wr23016, GP0, [lcdIO]
I2CIN SDA, Rd23016, GP1, [lcdCtrl]
lcdE = 1
I2COUT SDA, Wr23016, GP1, [lcdCtrl]
lcdE = 0
lcdRS = 1
I2COUT SDA, Wr23016, GP1, [lcdCtrl]
RETURN
F
o
r
E
l
e
c
t
r
o
n
i
c
s
You’ll recall from our previous work with LCDs that a
write can either be a command or a data byte for the
display. The LCD distinguishes between a command and
data by the state of the RS line; when we set the RS line
low, the byte written is interpreted as a command and,
when RS is high, the byte is interpreted as data to be
written to the current cursor position.
What you can see, then, is that LCD_Command is just
an entry point to the LCD_Write subroutine that takes
care of setting the RS line low. In order to make the code
work in other applications, we won’t assume anything
about the current state of RS; we’ll read it back, modify it
(make it 0), and then send it to the MCP23016. This must
look like a lot of work, especially compared to the direct bit
access we have on BASIC Stamp I/O pins. The truth of the
matter is that PBASIC shelters us from this kind of detail;
underneath the hood of the BASIC Stamp, the same kind
of process is happening when we manipulate a single pin.
NUTS & VOLTS
E
v
e
r
y
t
h
i
n
g
With RS setup properly, we can write the command that
was passed in the variable lcdIO. The command is written to
the LCD buss pins and then the LCD E pin is “blipped” high
momentarily. The process is the same as with manipulating
the RS pin — we read the current state, set it the way we want,
and then send it back. Notice that, when we take the E pin
back low, we return the RS line to a high (data mode). This
lets us enter LCD_Write with RS in the proper state.
One of the reasons I like LCDs so much is the ability
to have custom characters. Ten years ago, I created this
little animation of a chomping mouth — and I’ve brought
78
it back as part of the LCD interface test. The codes for
custom characters are stored in DATA statements and
then downloaded with a simple loop:
Download_Chars:
lcdIO = LcdCGRam
GOSUB LCD_Command
FOR addr = CC0 TO (CC2 + 7)
READ addr, lcdIO
GOSUB LCD_Write
NEXT
The process is straightforward: We set the cursor position
to the Character Generator RAM and then write the data
bytes that build those characters. Okay, we have what we
need to get information to the LCD, so let’s give it a try.
Main:
lcdIO = LcdCls
GOSUB LCD_Command
addr = Msg1
GOSUB Put_String
PAUSE 2000
The top of our demo starts by clearing the LCD. This
has a double purpose in that it also returns the LCD
cursor to the Home position. Then, we write a string to the
display with another subroutine. Like the custom character
data, strings are stored in DATA statements so they can
be re-used without consuming additional program space.
Here’s the code that writes a string to the LCD:
Put_String:
DO
READ addr, lcdIO
addr = addr + 1
IF (lcdIO = 0) THEN EXIT
GOSUB LCD_Write
LOOP
RETURN
The string display works by reading characters from a
DATA statement. The start of the string (and current character
in the loop) is pointed to by the variable addr. After
reading a character, the address gets updated, then is tested
for zero. If it is zero, then we terminate the loop and return
to the caller. If not, the character is sent to the LCD.
You may be wondering why we update the address
pointer right after the READ, when the value could be
zero. Well, by doing this, we can write two strings back-to-back without having to set the address of the second
string. The only condition is that the strings must be stored
in DATA statements in the order desired; otherwise, setting
the starting address for subsequent strings is required.
With data in the LCD, let’s see if we can read it back.
This code is a little more involved, but not really difficult.
What we have to do is set the GP0 pins as inputs and then
put the LCD in write mode by making the RW line high.
When we do that and set the E pin high, the LCD will
MAY 2004