but I think you know where I stand with that device. Still,
the idea is a good one: why not create a two-wire LCD
interface with a $2.00 part? So that’s what I did — using
the MCP23016, of course. That’s what I’m going to share
with you here.
Easy I/O — Easy LCD Terminal
What I like most about the MCP23016 is that it’s easy
to deal with; we simply set the DDRs for the ports as
needed, then write to them or read from them. Nothing
could be simpler. As an added bonus, each port (eight bits)
has a register that sets the polarity of the inputs. I like this
because it lets us read active-low inputs to the MCP23016
as 1 (high) when they are active.
So let’s get to it. What we’re going to do this month is
create an LCD terminal with the MCP23016, an LED, and
four active-low buttons. The demo program will test all of
the features of the terminal; later, we can strip out the
demo stuff and use the subroutines in other applications.
Figure 1 shows the schematic of the MCP23016
connections to the LCD. Notice that we’re using all eight
bits of GP0 (port 0) to connect to the LCD data buss. This
will simplify the code a bit versus the four-bit interface that
we typically use. We need three bits from GP1 (port 1) for
LCD control and the other bits are used to control the LED
(an output) and the four buttons (inputs).
The MCP23016 has an internal clock circuit that is
driven by an external resistor/capacitor combination. This
clock determines how quickly the MCP23016 can respond
to changes on its input pins to generate an interrupt
output. We’re not using that here, but we still need the RC
circuit for the MPC23016 to run. The values shown are
recommended by Microchip — just be aware that the
clock speed affects the MCP23016’s stand-by current
consumption. Be sure to download the MCP23016 docs
from Microchip for details on clock RC values and using
the interrupt output and capture registers.
Okay, the connections are simple enough — let’s jump
into the code. As with any I/O port, we have to initialize the
I/O direction bits as inputs or outputs.
I2COUT SDA, Wr23016, IODIR0, [%00000000]
I2COUT SDA, Wr23016, IODIR1, [%00001111]
I2COUT SDA, Wr23016, IPOL1, [%00001111]
We start with a PAUSE so that the LCD and the
MCP23016 can get through their internal reset operations.
The next step is to set the pin directions. Let me point out
a difference here between the MCP23016 and the BASIC
Stamp. In the MCP23016, an output bit is specified with
zero (0 looks like the letter O for output) and an input is
specified with one (1 looks like I for input).
This code is written to be obvious and, after you get
used to the device, you can take advantage of automatic
address indexing on writes and reads by writing to both I/O
DIR registers with one line of code:
I2COUT SDA, Wr23016, IODIR0, [%00000000, %00001111]
The final step in the setup process is to set the
polarity of the input bits on GP1.0–GP1.3. When writing to
a polarity register, a one bit inverts the input. Since we are
using active-low button circuits, we want them inverted —
hence the ones in bits zero through three.
Now that the ports on the MCP23016 are set up, it’s
time to initialize the LCD. For those of you who have worked
with LCDs previously, this code will look quite familiar:
lcdIO = %00110000
lcdIO = %00111000
lcdIO = %00001100
lcdIO = %00000110
Circle #63 on the Reader Service Card.