| 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 |