The code detailed here has been specifically written for the PICAXE and
targeted at LCD's which use the Hitachi HD44780 driver chips, which is by far
the great majority of LCD's which I have encountered.
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, although the unused Q1 output of the 74LS164 can be
used to control two E lines required by a 4 x 40 LCD. This is a
design change that is beyond the scope of this document.
The program code has been highly optimised, requiring just four dedicated byte
variables and uses just 85 bytes of program code space. The code is designed
for use with all PICAXE variants, although it is best used with the PICAXE-08M,
18A, 28 or 28A and is most suited for use with the PICAXE-18X, 28X and 40X with
their larger program memory capacities and extended subroutine capabilities.
Index
The Two-Wire Interface
The Two-Wire Interface Circuit
The Two-Wire Protocol
The Two-Wire Interface Software
The Three-Wire Interface
The Three-Wire Protocol
The Three-Wire Interface Software
The Two-Wire Interface
The design here is inspired by Myke Predko's
2-Wire LCD Interface but that
design is improved upon to give proper timing control for data stabilisation
before pulsing the LCD "E" signal, and uses a more commonly available
component.
This is the minimal for LCD interfacing without going to a serially controlled
LCD, and is considerably cheaper than purchasing a dedicated Serial LCD or
using a PICAXE or PICmicro to perform that task, but the penalty in a low cost
solution is an increase in time taken in updating the LCD, however, this can be
offset by moving to a Three-Wire LCD Interface described later. In many cases,
the simplicity and low cost of these solutions far outweigh their disadvantages.
The Two-Wire Interface Circuit
Mike's circuit uses a 74LS174 which is no longer easily obtainable ( ie,
Maplins Electronics in the UK doesn't
stock it ), so this is a re-design using the 74LS164 8-stage serial to
parallel converter.
+5V --------------.---------------------.---.------.
| | | | 1N914
.-------|---------------------|---|------|-----.-----.
.|. | | | | | |
| | 1K0 | 74LS164 | | | _|_ | LCD
|_| | .-----..------. | | | _\ /_ | .---------.
| `---| 1 Da +V 14 |---{ | | | | | |
DAT >-----^-----------| 2 Db Q7 13 |---|---|------|-----' | .-^--. |
| 3 Q0 Q6 12 |---|---|------|-----------|--->| 14 | DB7 |
| 4 Q1 Q5 11 |---|---|------|-----------|--->| 13 | DB6 |
.-------| 5 Q2 Q4 10 |---|---|------|-----------|--->| 12 | DB5 |
| .---| 6 Q3 /MR 9 |---' | | .-----|--->| 11 | DB4 |
.---|---|---| 7 0V CP 8 |---. | | | | | 10 | DB3 |
| | | `-------------' | | | | | | 9 | DB2 |
CLK >-----|---|---|---------------------' | | | | | 8 | DB1 |
| | `-------------------------|------|-----' | | 7 | DB0 |
| `-----------------------------|------|-----. `--->| 6 | E |
| .|. | | .--->| 5 | /WR |
| 10K | |<-. | `-----|--->| 4 | RS |
| Pot |_| `--|-----------|--->| 3 | Vo |
| | `-----------|--->| 2 | Vcc |
0V -------^---------------------------------^------------------^--->| 1 | Vdd |
`-.--' |
100nF Power Supply | |
decoupling not shown `---------'
The key to the circuit's simplicity is the 'AND Gate' formed between the DAT
signal from the PICAXE and the Q7 output from the 74LS164. It is a clever
technique from Electronics Now magazine which saves the need for a
single AND gate.
When either DAT or Q7 are low, the E signal to the LCD is kept
low. This allows the shift register to be cleared by keeping DAT low during
eight clock pulses. When clocking LCD controlling data into the 74LS164, the
low Q7 will keep E low regardless of DAT, and the E pulse for the LCD will
only occur when Q7 is high and DAT is high. This is achieved by clocking a '1'
into the 74LS164 as the first bit after clearing and by pulsing the DAT line
after the transfer has been completed.
The 1N914 diode is used to pull E down when Q7 is low ( clamping E when DAT is
high to about 0.7V, below the logic high threshold of the LCD input ) and can
probably be any high-speed switching diode, although any small-signal diode
such as a 1N4148 may work ( but is an untested theory ). The 1K0 resistor is to
limit the current to below 5mA ( at 5V ) when the DAT line is high and Q7 is
low. It is recommended that the DAT line is kept low whenever possible to
minimise current consumption.
It may be possible to replace the 74LS168 with a 74HC168 or 74HCT168, but that
is also an untested theory.
The Two-Wire Protocol
.----.----.----.----.----.----.----. .---.
DAT | | D7 | D6 | D5 | D4 | RS | ?? | | |
-----------------------------------' `----^----^----^----^----^----^------' `---
: :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 : :
.-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. .-. : :
CLK | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | : :
---' `-' `-' `-' `-' `-' `-' `-' `--' `--' `--' `--' `--' `--' `--' `--' `-----------
: : : :
---.---.---.---.---.---.---.---. .-------------
Q7 | | | | | | | | | : :
---^---^---^---^---^---^---^---^---------------------------------------' : :
.---.
E | |
-----------------------------------------------------------------------------' `---
Q7 - - - - - - - 0 0 0 0 0 0 0 0 1
Q6 - - - - - - 0 0 0 0 0 0 0 0 1 D7
Q5 - - - - - 0 0 0 0 0 0 0 0 1 D7 D6
Q4 - - - - 0 0 0 0 0 0 0 0 1 D7 D6 D5
Q3 - - - 0 0 0 0 0 0 0 0 1 D7 D6 D5 D4
Q2 - - 0 0 0 0 0 0 0 0 1 D7 D6 D5 D4 RS
Q1 - 0 0 0 0 0 0 0 0 1 D7 D6 D5 D4 RS ??
Q0 0 0 0 0 0 0 0 0 1 D7 D6 D5 D4 RS ?? 0
Clearing the 74LS164 is achieved by setting DAT low (0) and sending eight high
going CLK pulses.
DAT is then set high (1) and a further CLK pulse is issued, followed by the
data bits for DB7, DB6, DB5, DB4 and RS each with their own CLK pulses.
A further CLK pulse must be issued ( the state of the DAT line does not matter
during this CLK pulse ), followed by a final CLK pulse with DAT set low.
After the transfer is completed, DAT must be set high to active E and then
brought low to clear E. The DAT line must then remain low until the 74LS164 has
been cleared ( by issuing eight CLK pulses with DAT low ).
Note that by clearing the 74LS164 at Power-On Reset ( eight CLK pulses with DAT
low ), and ensuring that DAT is low when the two CLK pulses following the
sending of the RS data bit are issued, it is possible to send just six pulses to
guarantee that the 74LS164 will be cleared. This will give a slight speed
improvement to every transfer of data to the 74LS164.
By tracking what's been clocked into the 74LS164 it is also possible to minimise
the number of CLK pulses required to perform a clear and to set the data
transfer value, however, the time taken to perform such an optimisation probably
outweighs delivering all clock pulses regardless on a PICAXE.
The Two-Wire Interface Software
There are three routines which are used to initialise and control the LCD ...
GOSUB InitialiseLcd ; Initialise the LCD
byte = ... ; Send byte to LCD Data Register
GOSUB SendDataByte
byte = ... ; Send byte to LCD Command Register
GOSUB SendCmdByte
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.
For a more comprehensive review of how to use the routines, please see the
article on interfacing LCD's to a PICAXE in the more traditional parallel
manner. The user callable routines presented here are compatible with software
that uses that design.
PICAXE LCD Interfacing
The code requires five variables to be defined ...
SYMBOL get = b9
SYMBOL byte = b10
SYMBOL dataOut = b11
SYMBOL bitNumber = b12
SYMBOL rsbit = b13
Note that the 'get' variable is only used within the 'InitialiseLcd' routine
and therefore 'b9' can be re-used with your own program after the LCD
has been initialised.
The 'byte', 'dataOut' and 'bitNumber' variables are only used in the
'InitialiseLcd', 'SendDataByte' and 'SendCommandByte' routines, and therefore
'b10', 'b11', 'b12' and 'w5' can be re-used within your own program, although
they will have their values 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 code uses 'SYMBOL DAT_PIN = pinN' to optimise the code ( where
N is the number used in the 'SYMBOL DAT = N' definition ), but
due to a limitation of the compiler this means that only certain pins can be
used for connection to a PICAXE ...
Variant DAT pin allowed
PICAXE 08 or 08M 1, 2 or 4
PICAXE 18, 18A and 18X 0, 1, 2, 6 or 7
PICAXE 28, 28A, 28X and 40X Any pin
The CLK line can be connected to any PICAXE Digital Output pin. For maximum
code size optimisation it is recommended that DAT and CLK are connected to pins
0 and 1, which line connects to which pin is not important ...
Variant DAT pin CLK pin
PICAXE 08 or 08M 1 0
PICAXE 18, 18A and 18X 1 or 0 0 or 1
PICAXE 28, 28A, 28X and 40X 1 or 0 0 or 1
For ease of using the code on a variety of PICAXE processors, it is recommended
that the DAT line is connected to Output Pin 1 and the CLK line is connected to
Output Pin 0.
The complete program for controlling a HD4470 based LCD through a 74LS168,
exclusing the User Program code, is given below, The code uses the recommended
connection pins for the DAT and CLK lines, and the SYMBOL definitions for DAT,
CLK and DAT_PIN will need to be changed if you choose to use alternative pins.
SYMBOL DAT = 1 ; Pin number of DAT line
SYMBOL CLK = 0 ; Pin number of CLK line
SYMBOL DAT_PIN = pin1 ; Pin number of DAT line
SYMBOL CLK_PULSE_LENGTH = 1 ; 10uS
SYMBOL E_PULSE_LENGTH = 1 ; 10uS
SYMBOL RSCMDmask = %00000000 ; Select Command register
SYMBOL RSDATmask = %00001000 ; Select Data register
SYMBOL get = b9
SYMBOL byte = b10
SYMBOL dataOut = b11
SYMBOL bitNumber = b12
SYMBOL rsbit = b13
PowerOnReset:
GOSUB InitialiseLcd
; User Program Here
END
InitialiseLcd:
FOR get = 0 TO 5
READ get,byte
GOSUB SendInitCmdByte
NEXT
' Nibble commands - To initialise 4-bit mode
EEPROM 0,( $33 ) ; %001?---- %001L---- Display Format
EEPROM 1,( $32 )
' Byte commands - To configure the LCD
EEPROM 2,( $28 ) ; %00101000 %001LNF00 Display Format
EEPROM 3,( $0C ) ; %00001100 %00001DCB Display On
EEPROM 4,( $06 ) ; %00000110 %000001IS Cursor Move
; L : 0 = 4-bit Mode 1 = 8-bit Mode
; N : 0 = 1 Line 1 = 2 Lines
; F : 0 = 5x7 Pixels 1 = N/A
; D : 0 = Display Off 1 = Display On
; C : 0 = Cursor Off 1 = Cursor On
; B : 0 = Cursor Steady 1 = Cursor Flash
; I : 0 = Dec Cursor 1 = Inc Cursor
; S : 0 = Cursor Move 1 = Display Shift
EEPROM 5,( $01 ) ; Clear Screen
RETURN
SendInitCmdByte:
PAUSE 15 ; Delay 15mS
SendCmdByte:
rsbit = RSCMDmask ; Send to Command register
SendDataByte:
dataOut = byte & %11110000 | rsbit
GOSUB TransferTo74LS164
dataOut = byte * %00010000 | rsbit
GOSUB TransferTo74LS164
rsbit = RSDATmask ; Send to Data register next
RETURN
TransferTo74LS164:
LOW DAT ; Clear 74LS164
FOR bitNumber = 0 TO 7
PULSOUT CLK,CLK_PULSE_LENGTH
NEXT
HIGH DAT ; Transfer data
PULSOUT CLK,CLK_PULSE_LENGTH
FOR bitNumber = 0 TO 6
DAT_PIN = dataOut / $80
PULSOUT CLK,CLK_PULSE_LENGTH
dataOut = dataOut * 2
NEXT
PULSOUT DAT,E_PULSE_LENGTH ; Pulse E
RETURN ; Completed transfer
If you need the absolutely minimum code size and are prepared to have any data
held in the 'w0' variable altered when the LCD routines are called, and accept
that the execution time will increase, then the 'TransferTo74LS164' routine can
be replaced with the code below, which saves 6 bytes of code space ...
TransferTo74LS164:
w0 = dataOut / 2 | $80 ; Format data
FOR bitNumber = 0 TO 15 ; Clear and transfer data
DAT_PIN = bit15
PULSOUT CLK,CLK_PULSE_LENGTH
w0 = w0 * 2
NEXT
PULSOUT DAT,E_PULSE_LENGTH ; Pulse E
RETURN ; Completed transfer
The Three-Wire Interface
The three-wire interface circuit is the same as the
Two-Wire Interface Circuit except
that the Memory Reset pin of the 74LS164 ( /MR ) is not connected to +5V, but
is driven from a PICAXE Digital Output, CLR. This speeds up LCD updating
because it is no longer necessary to use eight clock pulses to clear the
74LS164 before every LCD control byte is sent.
If you are planning to build either a two-wire or three-wire LCD interface on a
breadboard, veroboard ( stripboard ) or as a PCB, it would probably make sense
to use a three pin molex connector and a link so /MR can either connect to an
external CLR line for three-wire use, or to +5V for two-wire use.
The Three-Wire Protocol
---. .---------------------------------------------------
CLR | |
`-'
: .----.----.----.----.----.----.----. .---.
DAT : | | D7 | D6 | D5 | D4 | RS | ?? | | |
--------' `----^----^----^----^----^----^-----' `---
: : :
: 1 2 3 4 5 6 7 8 : :
: .-. .-. .-. .-. .-. .-. .-. .-. : :
CLK : | | | | | | | | | | | | | | | | : :
---------' `--' `--' `--' `--' `--' `--' `--' `----------
: : : :
---. .------------
Q7 | | : :
`----------------------------------------' : :
.---.
E | |
-------------------------------------------------' `---
Q7 0 0 0 0 0 0 0 0 1
Q6 0 0 0 0 0 0 0 1 D7
Q5 0 0 0 0 0 0 1 D7 D6
Q4 0 0 0 0 0 1 D7 D6 D5
Q3 0 0 0 0 1 D7 D6 D5 D4
Q2 0 0 0 1 D7 D6 D5 D4 RS
Q1 0 0 1 D7 D6 D5 D4 RS ??
Q0 0 1 D7 D6 D5 D4 RS ?? 0
Clearing the 74LS164 is achieved by sending a low going CLR pulse. The state
of the DAT line does not matter at this time.
DAT is then set high (1) and a further CLK pulse is issued, followed by
the data bits for DB7, DB6, DB5, DB4 and RS each with their own CLK pulses.
A further CLK pulse must be issued ( the state of the DAT line does not matter
during this CLK pulse ), followed by a final CLK pulse with DAT set low.
After the transfer is completed, DAT must be set high to active E and then
brought low to clear E. The DAT line must then remain low until the 74LS164 has
been cleared.
Providing the CLR line is kept high by the PICAXE ( or wired to +V ), the code
used to control the two-wire interface can be used with the three-wire interface
without change, but the code will run slower than that designed for the
three-wire interface.
The Three-Wire Interface Software
The software used for the three-wire interface is the same as the
Two-Wire Interface Software with
two changes.
The following constant definitions must be added at the start of the source
code ...
SYMBOL CLR = ? ; Pin number of CLR line
SYMBOL CLR_PULSE_LENGTH = 1 ; 10uS
The CLR line can be connected to any PICAXE Digital Output pin.
The 'TransferTo74LS164' routine needs to be replaced with the following
code ...
TransferTo74LS164:
PULSOUT CLR,CLR_PULSE_LENGTH ; Clear 74LS164
HIGH DAT ; Transfer data
PULSOUT CLK,CLK_PULSE_LENGTH
FOR bitNumber = 0 TO 6
DAT_PIN = dataOut / $80
PULSOUT CLK,CLK_PULSE_LENGTH
dataOut = dataOut * 2
NEXT
PULSOUT DAT,E_PULSE_LENGTH ; Pulse E
RETURN ; Completed transfer
PICAXE is a trademark of Revolution Education Ltd.
PICmicro is a registered trademark of Microchip Inc.