PICAXE LCD Interfacing | |
| LCD's are often one of the most useful
interfaces which can be added to a microcontroller, either as part of a
self-contained project, or as a sub-system of a larger project.
Connecting an LCD to a PICAXE provides a simple and easy mechanism to provide a low-cost serially driven LCD display which can be connected to other PICAXE's, microcontrollers and even PC's and PDA's. The code detailed here has been specifically written
for LCD's which use the Hitachi HD44780 driver chips, which is by far the
great majority of LCD's which I have encountered.
All LCD's I have tested, in a variety of display size
formats ( from 1 x 8 to 4 x 20 ), from
a number of different manufacturers, which all use the HD44780 chip have
worked with the code and 100% compatible driver chips should also work,
but the code is not guaranteed to work with all HD44780-based devices, or
those which do not use the genuine Hitachi chip.
Note that the code will not work with 4 x 40 LCD's because
they are internally constructed from two 2 x 20 controllers and
require an additional control line.
The program code has been highly optimised, requiring just two
dedicated byte variables and uses just 51 bytes of program code space.
Important Notes
Hardware Interface
Software
LCD Control
PICAXE Documentation Errors It should also be noted that there is an error in the instructions
on how an LCD should be connected to the PICAXE in the Electronics
Interfacing Circuits datasheet as provided with the Programming Editor
software version 4.1.16 and earlier.
On some pages the connection instructions indicate that DB4 of the LCD
is connected to Output Pin 7 of the PICAXE, and correspondingly through to
DB7 being connected to Output Pin 4.
This is not correct. The connections described result in a 'swapped
nibble' which will prevent the LCD from working as expected. The correct
connections should be DB4 to Output Pin 4 through to DB7 to Output Pin 7.
The wiring connections on this page are, and always have been, correct in
this respect.
The instructions provided in the Electronics Interfacing
Circuits datasheet also indicate that the unused DB0 through DB4 lines
"should be" connected to 0V. This may not be necessary for all models of
LCD, and most datasheets for devices using the HD44780 driver indicate
that the unused lines can be left unconnected, or 'floating', as they are
in the circuits given later.
It is recommended that you consult your LCD datasheet to check the
requirements for connecting DB0 through DB3 in 4-bit mode, but conncting
them directly to 0V via low value resistors should not do any harm, nor
should connecting them directly to 0v providing that the LCD R/W
line is always connected to 0v.
Additionally, as recommended by Revolution Education Limited, the
connections to the LCD, DB4 to DB7, RS and E, can be made through 660R
resistors.
LCD Pin Numbering Note that the pin numbering shown for the LCD in the diagrams in this
document is that which is usually found on HD44780-based LCD modules, but
it is not the only scheme used.
Most LCD modules will have a single 14-way connector, and 16-way if
backlit, and are normally numbered as shown, with Pin 1 being
0V ( or "Vdd" ). The numbering can however be reversed, and
some modules are fitted with 2x7 and 2x8-way connectors, again with
varying pin numbering schemes.
Although not common, some LCD modules may have entirely different
pinouts to those shown.
You must determine the correct pinout and numbering scheme and the
connections required by the LCD from the user manual or other
documentation provided with the LCD before connecting the LCD, as
incorrect connection may cause permanent damage to the LCD, PICAXE or
both.
The connection information is provided as is and I cannot be
held repsonsible for the consequences arising from any incorrect
connection of an LCD.
Circuit Changes The information on this page was changed in May 2004 and the wiring
configuration and software is different to that used before then. The
earlier software will not work with the current wiring specified, and the
latest software will not work with the earlier wiring configuration.
The modification necessary to the old wiring configuration to be
compatible with the latest software is very simple to implement, involving
the swapping of two connection signals.
It came to my attention that the wiring configuration I was using was
different to that used in the Electronics Interfacing Circuit
datasheet ( AXE001_pic_electronics.pdf ) provided by
Revolution Education Limited - the connections for RS and E were
swapped - which meant that hardware had to be changed to use my own
code in place of Revolution Education Limited's.
In order to allow my code to simply replace theirs, I have rewritten my
software to be compatible and have changed my wiring configuration to
match this.
If you have previously used the information on this page to create an
LCD interface, it is recommended that you rewire your interface, swapping
RS with E, and modify your software accordingly.
Note that in this, and the following circuits, the Serial In line is
permanently connected to 0V. This is to simplify the circuit diagram; you
would normally include a Program Download interface for Serial In and
Serial Out connections.
The LCD is likely to be irreparably damaged by voltages which exceed 5V
by any considerable amount and especially when operated from a 6V power
supply, such as when using a 4 x 1.5V battery supply.
The LCD, although probably avoiding damage, may fail to operate
correctly ( and the display may appear blank or very
faint ) when the supply is much less than 5V, and problems may be
observed when operated from a 4.5V power supply, such as when using a
3 x 1.5V battery supply.
It is recommended that all LCD's are powered through a regulated 5V
power supply, preferably the same supply which is used to power the
PICAXE, but it may also be powered by a separate supply. When operating
with a separate supply, special consideration should be given to the
PICAXE power supply voltage as this will affect the voltages delivered on
the PICAXE Output Pins; if the voltage is too low, the PICAXE may not be
able to control the LCD correctly.
Take care not to inadvertently connect reverse power to the LCD as this
will almost certainly destroy the device.
You may therefore find that the LCD contrast is acceptable when the
'Vo' pin is wired directly to 0V or through a low value resistor; this
makes the LCD even simpler to wire-up and uses the minimum amount of board
space.
Note that some LCD's may be permanently damaged if 'Vo' is taken up to
5V or close to it, so check the datasheet and start with the contrast pot
set to provide 0V. If the contrast is externally adjustable, it would be a
wise precuation to put an additional resistor ( probably
2K2 ) between the top of the 10K potentiometer and the +5V supply to
limit 'Vo'.
Note that the 'get' variable is only used within the 'InitialiseLcd'
routine and therefore 'b11' can be re-used with your own program after the
LCD has been initialised.
The 'byte' variable is only used in the 'InitialiseLcd' routine and to
specify the data which is to be sent using the 'SendDataByte' and
'SendCommandByte' routines, and therefore 'b12' can be re-used within your
own program, although it will have its value changed when any of these
routines are called.
The 'rsbit' variable must be preserved intact during the operation of
the program and so 'b13' ( and consequently 'w6' ) must not
be used by your own code unless placed somewhere else and restored after
use.
The 'InitialiseLcd' routine must be called once, at the start of the
program.
The 'SendDataByte' and 'SendCmdByte' routines are used to send data
bytes to the LCD data and command registers respectively. This allows data
to be displayed on the LCD and the cursor and other attributes of the LCD
and its display to be altered. Before calling either of the two routines,
the data byte to be sent must be placed in the 'byte' variable. The value
put into the 'byte' variable is not changed when the routines are called.
Examples
As can be seen, the three routines are tightly integrated, which is the
key to the compactness of the program code.
The 'rsbit' variable is used to keep track of which register will be
written to next; the LCD Command or Data Register, and must be preserved
between calls to the 'SendDataByte:' routine. The 'SendCmdByte:' routine
simply sets the 'rsbit' varaible so the data written goes to the LCD
Command Register. The 'SendDataByte:' routine relies upon 'rsbit' being
set correctly when it is called, and always sets the 'rsbit' variable so a
subsequent call to the routine will send further data bytes to the LCD
Data Register.
The 'SendInitCmdByte:' routine is used solely to send nibble and byte
commands to the LCD Control Register during initialisation of the LCD. The
initialisation routines for an LCD are very clearly defined, and those
familiar with them will observe that the initialisation used in this code
does not conform entirely to the sequence and timing specified.
This has not been shown to be a problem in practice, and all HD44780-based
LCD's which I have tested have initialised and worked fine with the code,
although it may not work with all HD44780-based devices or non-Hitachi
chipsets, even those which claim to be 100% compatible.
In most LCD initialisation code, you will see a variety of delays used
which decrease as initialisation progresses. This code uses a fixed delay
of 15mS between each byte sent ( and very little delay between
the two nibbles of each byte ). Although this adds unneccessary delay
to initialisation, it amounts to less than 100mS overall, and is a price
worth paying for the huge reduction in program code it achieves.
The 'PAUSE 15' delay is fine at 4MHz, but will usually need to be
extended to 'PAUSE 30' when operating at 8MHz and to 'PAUSE 60' at 16MHz.
The two 'PULSOUT E,1' statements are suitable for any speed operation.
The routines rely upon their own execution times to ensure that data is
not sent before the LCD is ready for the next data sent, which is fine for
all but two commands sent to the LCD Command Register - Clear
Display ($01) and Return Home ($02 and $03). The speed of PICAXE
execution should mean that there is no problem with these commands at even
16MHz operation, but should any problems be encountered using these
commands, it may be necessary to add a 2mS delay after they are issued. It
is worthwhile trying your code without the delays first, as it is unlikely
you will have a program which causes a problem. The Return Home command
can usually be replaced by a command which explicitly sets the next
character position to be written to - Set DDRAM Address
0 ($80) - which requires no delay after execution. The only time
this may not be possible is if you are deliberately shifting or scrolling
the display under program control to achieve some desired effect.
If it is not desirable to have these two bits cleared while interacting
with the LCD, the rouines can be modified as follows ...
The trick used is to recover the contents of SFR at location $30 which
is a copy of the current output pin levels. This allows the levels of
Output Pins 0 and 1 to be recovered and then set as they were previously
when the 'pins =' assignments are performed.
The routines require slightly more code space than the best optimised
versions, but it is no longer necessary to preserve the 'rsbit' variable
between calls to the 'SendCmdByte:' and 'SendDataByte:' routines. This
variable can be used outside the routines but it will be corrupted
whenever the routines are called.
For the program to work correctly, the LCD must be attached to the
PICAXE as shown in the diagrams at the top of the page.
The commonest commands that will be sent to the LCD are as follows - Clearing the display ... byte = $01 : GOSUB SendCmdByte ; Clear Display PAUSE 2 ; Delay may not be needed Specifying where to write to .. byte = $80 : GOSUB SendCmdByte ; Start of Line 1 byte = $C0 : GOSUB SendCmdByte ; Start of Line 2 byte = $A0 : GOSUB SendCmdByte ; Start of Line 3 byte = $E0 : GOSUB SendCmdByte ; Start of Line 4 Programming User-Defined Charaters ... byte = $40 : GOSUB SendCmdByte ; User-Defined Character 0 byte = $48 : GOSUB SendCmdByte ; User-Defined Character 1 byte = $50 : GOSUB SendCmdByte ; User-Defined Character 2 byte = $58 : GOSUB SendCmdByte ; User-Defined Character 3 byte = $60 : GOSUB SendCmdByte ; User-Defined Character 4 byte = $68 : GOSUB SendCmdByte ; User-Defined Character 5 byte = $70 : GOSUB SendCmdByte ; User-Defined Character 6 byte = $78 : GOSUB SendCmdByte ; User-Defined Character 7
Character Addresses are sent to the LCD by using the following code ... byte = ... ; Set Character Address GOSUB SendCmdByte The value assigned to the 'byte' variable will determine the Character Address and will depend upon the character position where you wish to place the character and the size of the display ... 8 x 1 - 8 characters x 1 line
8 x 2 - 8 characters x 2 lines
Line 2 : $C0 .. $C7 16 x 1 - 16 characters x 1 line
Note that the 16 x 1 display is actually an 8 x 2 internally which is re-arranged to give the correct display. After writing the 7th character, the character address has to be changed to the start of Line 2 to write the 8th character. 16 x 2 - 16 characters x 2 lines
Line 2 : $C0 .. $CF 16 x 4 - 16 characters x 4 lines
Line 2 : $C0 .. $CF Line 3 : $A0 .. $AF Line 4 : $E0 .. $EF 20 x 1 - 20 characters x 1 line
20 x 2 - 20 characters x 2 lines
Line 2 : $C0 .. $D3 20 x 4 - 20 characters x 4 lines
Line 2 : $C0 .. $D3 Line 3 : $A0 .. $B3 Line 4 : $E0 .. $F3
User-Defined CharactersUser defined characters are exactly like other characters which can be displayed on the LCD but rather than have their 'image' defined in unchangeable Read Only Memory, the image is defined as a 'pixel bitmap' which is held in writeable memory.There are eight User-Defined Characters which can be displayed by simply telling the LCD to display the charcters $00 to $07 ... GOSUB InitialiseLcd ; Initialise the LCD FOR b0 = $00 to $07 ; Display user defined characters byte = b0 GOSUB SendDataByte NEXT If you run this program, you will most likely find that the display shows little but gibberish; this is because the character bitmaps have not been defined and have no meaningful values whenever the LCD is powered-up. Every User-Defined Character is made up from a 7x5 bitmap; seven lines of five bits, and these are held in eight consecutive bytes of memory within the LCD chip. Each byte of memory holds one line's worth of pixels; the three most significant bytes are zero, the remaining five bits per byte, left to right, make up that charcter's line display, also left to right, when displayed. The eigth byte of the image map should be set to zero. The data values to define a User-Defined Character have a bit set to represent where a pixel is on in the image, and a cleared (zero) bit when off. The following shows the data values to create a better looking 'g' that the one which is normally displayed .. Line 1 %00000 ----- Line 2 %00000 ----- Line 3 %01110 -###- Line 4 %10001 #---# Line 5 %01111 -#### Line 6 %00001 ----# Line 7 %01110 -###- Line 8 %00000 ----- To program the bitmap for a User-Defined Character into the LCD, a command must be sent to the LCD Command Register to indicate which User-Definded Character is to be programmed, followed by the bitmap which is sent to the LCD Data Register. The command needed to specify the character to program the bitmap for has the following format - %01ccc000 Where 'ccc' is the number of the User-Defined Character, 0 to 7. The value for the command can either be determined before writing the code or may be calculated at runtime. The following code demonstrates how to program the bitmap to be used as User-Defined Character number 3, and displays it on the LCD ... GOSUB InitialiseLcd ; Initialise the LCD byte = 3 * 8 | $40 ; Program User Defined Character 3 GOSUB SendCmdByte byte = %11111 : GOSUB SendDataByte ; ##### byte = %10001 : GOSUB SendDataByte ; # # byte = %11111 : GOSUB SendDataByte ; ##### byte = %00100 : GOSUB SendDataByte ; # byte = %10101 : GOSUB SendDataByte ; # # # byte = %01110 : GOSUB SendDataByte ; ### byte = %00100 : GOSUB SendDataByte ; # byte = %00000 : GOSUB SendDataByte ; byte = $80 ; Display at start of Line 1 GOSUB SendCmdByte byte = $03 ; Display User Defined Character 3 GOSUB SendDataByte An alternative, and less program code hungry solution to programming User-Defined Characters is to store the character definitions in Eeprom as follows ... GOSUB InitialiseLcd ; Initialise the LCD EEPROM $40,(3) ; Program User Defined Character 3 EEPROM ( %11111 ) ; ##### EEPROM ( %10001 ) ; # # EEPROM ( %11111 ) ; ##### EEPROM ( %00100 ) ; # EEPROM ( %10101 ) ; # # # EEPROM ( %01110 ) ; ### EEPROM ( %00100 ) ; # EEPROM ( $80 ) ; get = $40 ; Point to Eeprom GOSUB ProgramCgRam ; Define User-Define Character byte = $80 ; Display at start of Line 1 GOSUB SendCmdByte byte = $03 ; Display User Defined Character 3 GOSUB SendDataByte END ProgramCgRam: READ get,byte byte = byte * 8 | $40 GOSUB SendCmdByte ProgramCgRamLine: get = get + 1 READ get,byte GOSUB SendDataByte IF byte < $80 THEN ProgramCgRamLine RETURN Note that in both cases it is necessary to re-position the cursor before sending data for display to the screen having completed a User-Defined Character definition. For this reason, it is usually common to have User-Defined Character Definitions at the start of the program, immediately after initialisation, knowing that the cursor will be positioned before any data is written for display. One of the great uses for User-Defined Characters is in re-defining the displayed images for lower-case 'g', 'p' 'q' and 'y' characters. Because the bottom, eight, line of the character can be displayed, it is possible to create a 'true descender'. In some cases this may clash with the rest of the display's appearance, but the display can still often be improved. The following profgram will display five 'g' characters, the first, third and fith are the normal 'g', the second is the improved version ( using User-Defined Character 1 ) and the fourth with a true descender ( using User-Defined Character 2 ) ... GOSUB InitialiseLcd ; Initialise the LCD EEPROM $40,(1) ; Program User Defined Character 1 EEPROM ( %00000 ) ; EEPROM ( %00000 ) ; EEPROM ( %01111 ) ; #### EEPROM ( %10001 ) ; # # EEPROM ( %01111 ) ; #### EEPROM ( %00001 ) ; # EEPROM ( %01110 ) ; ### EEPROM ( $80 ) ; EEPROM $50,(2) ; Program User Defined Character 2 EEPROM ( %00000 ) ; EEPROM ( %00000 ) ; EEPROM ( %01111 ) ; #### EEPROM ( %10001 ) ; # # EEPROM ( %10001 ) ; # # EEPROM ( %01111 ) ; #### EEPROM ( %00001 ) ; # EEPROM ( $8E ) ; ### get = $40 ; Point to Eeprom GOSUB ProgramCgRam ; Define User-Define Character get = $50 ; Point to Eeprom GOSUB ProgramCgRam ; Define User-Define Character byte = $80 ; Display at start of Line 1 GOSUB SendCmdByte byte = "g" ; Display Default 'g' GOSUB SendDataByte byte = $01 ; Display User Defined Character 1 GOSUB SendDataByte byte = "g" ; Display Default 'g' GOSUB SendDataByte byte = $02 ; Display User Defined Character 2 GOSUB SendDataByte byte = "g" ; Display Default 'g' GOSUB SendDataByte
PICAXE is a trademark of Revolution Education Ltd. PICmicro is a registered trademark of Microchip Inc. | ||||
First
published on Wednesday the 3rd of December, 2003 at 18:09:58 Last upload was on Tuesday the 18th of January, 2005 at 01:49:59 |