Driving an Hitachi 44780 based LCD module

To learn more about how to control a 44780 based LCD, go here first so that you get an understanding of how to control this module.

In the meantime, here are three solutions for controlling a 44780 based module with a Parallax BS2.

Each program displays the message "Lennard Electronics www.lennard.net.nz" on the LCD.

Notes: I have used a 2 x 20 LCD. If you are using a 2 x 16 LCD, you will need to make a few minor changes to the code. Also, regarding the contrast pin (pin 3). The easiest thing to do, is to ground pin 3. Of course, you will not have control over contrast (you'll get full contrast), but it will get you started quicker. Details on contrast adjustment can be found on the page linked to above.

To save Microcontroller pins:

-or-

-or-

 

SIPO solution:

'{$stamp BS2}

'[DECLARE VARIABLES]

StartScreen DATA "Lennard Electronics www.lennard.net.nz" 'Writes this to EEPROM
'at compile time

Clock CON 0
' Port 0 of the stamp = Clock to 4094.
DataPack CON 1
' Port 1 of the stamp = Data pin to 4094
Strobe CON 2
' Port 2 of the stamp = Strobe pin on the 4094
Outputenable CON 3
' Port 3 of the stamp = Outputenable on the 4094
RS CON 4
' Port 4, Low = Instruction to the LCD, High = Data to the LCD
RW CON 5
' Port 5, Low = Write to the LCD, High = Read from the LCD
EnableLCD CON 6
' Port 6, Enable LCD
character VAR BYTE
cursorposition VAR BYTE
i VAR BYTE
'Just a for loop variable

'[MAIN CODE BEGINS]
LOW EnableLCD
LOW outputenable
GOSUB resetcmos
GOSUB setuplcd
GOSUB DisplayStartupMessage
END

'[END MAIN CODE]

'[ROUTINES]

resetcmos: 'Reset the 4094
SHIFTOUT datapack, clock, msbfirst, [0] 'clear the 4094's registers
PULSOUT Strobe,1
HIGH outputenable
RETURN

setuplcd: 'Now, setup the LCD
HIGH EnableLCD
LOW RS
'sending an Instruction to the LCD
LOW RW
'Writing to the LCD
SHIFTOUT datapack, clock, msbfirst, [56]
'LCD = 8 bits, 2 lines, 5x7 font
PULSOUT Strobe,1
LOW EnableLCD
PAUSE 100
'Turn the display off
HIGH EnableLCD
SHIFTOUT datapack, clock, msbfirst, [8]
PULSOUT Strobe,1
LOW EnableLCD
PAUSE 100
'Turn the display on, without a cursor
HIGH EnableLCD
SHIFTOUT datapack, clock, msbfirst, [12]
PULSOUT Strobe,1
LOW EnableLCD
PAUSE 100
'Clear the display
HIGH EnableLCD
SHIFTOUT datapack, clock, msbfirst, [1]
PULSOUT Strobe,1
LOW EnableLCD
HIGH RS
PAUSE 1
RETURN

DisplayStartupMessage:
FOR i = 0 to 37
READ i, character
GOSUB sendtoLCD
NEXT
RETURN

newline: 'Start on next line
LOW RS
HIGH EnableLCD
SHIFTOUT datapack, clock, msbfirst, [192]
PULSOUT Strobe,1
LOW EnableLCD
HIGH RS
PAUSE 1
RETURN

sendtoLCD:
HIGH EnableLCD
SHIFTOUT datapack, clock, msbfirst, [character]
PULSOUT Strobe,1
LOW EnableLCD
PAUSE 1
GOSUB cursor
RETURN

ClearDisplay:
LOW RS
HIGH EnableLCD
SHIFTOUT DataPack,Clock,MSBFIRST,[1]
PULSOUT Strobe, 1
LOW EnableLCD
PAUSE 100
'Turn the display on, with a cursor
HIGH EnableLCD
SHIFTOUT datapack, clock, msbfirst, [13]
PULSOUT Strobe,1
LOW EnableLCD
PAUSE 100
HIGH RS
cursorposition = 0
RETURN

cursor:
cursorposition=cursorposition+1
IF NOT cursorposition = 20 then carryon
GOSUB newline
carryon:
RETURN
'[END OF ROUTINES]

 

I2C solution:

For more information on how to implement I2C, go here.

Click here for an example of how to drive a Matrix Orbital LCD display with built in I2C support.

Notes: the resistors are needed. The outputs of all I2C devices are open drain, so the 10k resistors are needed as pull up resistors. As the Stamp has totem pole outputs, there is a slight chance that a bus short could occur when being used with I2C, so the two 220 ohm resistors limit the current if that were to happen (example, if the I2C device pulled SDA low when the Stamp was outputing a High.

 '{$STAMP BS2}

'I2C test program. 4/9/2002 Ben Lennard
'Bit Bashing I2C on a Parallax BS2
'Write to an LCD via the 8 ports of a PCF8574A Bidirectional 8 bit I/O 'chip meaning only 5 pins needed (4 if you don't need R/W on the LCD)

'STAMP EEPROM DATA
Companyname DATA "Lennard Electronics "
URL DATA "www.lennard.net.nz "

'CONSTANTS

SCL CON 0
'I2C Clock line
SDA CON 1
'I2C Data line
LCD_RS CON 2
LCD_E CON 3
PCF8574_Write CON %01110000

'VARIABLES
ack VAR BIT
'Acknowledge from the I2C bus
I2C_data VAR BYTE
'Data to/from the I2C bus
i VAR BYTE
'just a for loop variable
LCDcharacter VAR BYTE
start VAR BYTE
'Starting point in Stamp's EEPROM to read from
finish VAR BYTE
'Finishing point in Stamp's EEPROM to read from

 

DIRS=%1111111111111111
LOW LCD_RS
LOW LCD_E

'MAIN CODE
Main:
GOSUB LCD_Init
'Set up the LCD
GOSUB DisplayStartupMessage
'Display a Message at System Power On
'[END MAIN CODE]

END

'[SUBROUTINES]

'************************ LCD SOUBROUTINES ********************************
LCD_Init:
PAUSE 500
' let the LCD settle
LCDcharacter = 56
' multi-line mode
GOSUB LCD_Command
PAUSE 5
PULSOUT LCD_E,1
PULSOUT LCD_E,1
LCDcharacter = 6
' inc crsr, no disp shift
GOSUB LCD_Command
PAUSE 5
RETURN

LCD_Command:
LOW LCD_E
LOW LCD_RS

sendtoLCD:
GOSUB StartI2C
I2C_data = PCF8574_Write
'The address of the IC on the I2C bus
GOSUB Write_data
I2C_data = LCDcharacter
GOSUB Write_data
GOSUB StopI2C
PULSOUT LCD_E,1
HIGH LCD_RS
RETURN

ClearDisplay:
LCDcharacter = 1
GOSUB LCD_Command
LCDcharacter = 12
GOSUB LCD_Command
RETURN

newline:
'Start on next line
LCDcharacter = 192
GOSUB LCD_command
RETURN
'^^^^^^^^^^^^^^^^^^^^^^^ LCD SUBROUTINES ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 

'*********************** I2C SUBROUTINES **********************************
'Start Procedure. Set start condition on bus: SDA Hi-Lo while SCL Hi

StartI2C:
HIGH SDA
HIGH SCL
LOW SDA
LOW SCL
RETURN

'Stop Procedure. Set stop condition on bus: SDA Lo-Hi while SCL Hi
StopI2C:
LOW SDA
HIGH SCL
HIGH SDA
RETURN

'Write Address/Data Procedure
Write_data:
shiftout SDA, SCL, msbfirst, [I2C_data]
'Check for Receiver Acknowledge
RX_ACK:
HIGH SDA
DIRS=%111111111111101
HIGH SCL
ack = IN1
LOW SCL
DIRS=%1111111111111111
'if ack = 1 then indicate_NO_ACK
'debug "Acknowledged", 13
'RETURN
'indicate_NO_ACK:
' debug "NO Acknowledge", 13

RETURN

'^^^^^^^^^^^^^^^^^^^^^^^^^^^^ I2C SUBROUTINES ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

DisplayStartupMessage: ' "Lennard Electronics "
GOSUB ClearDisplay
' "www.lennard.net.nz "
start = 0
finish = 18
GOSUB ReadEEPROM
GOSUB newline
start = 19
finish = 36
GOSUB ReadEEPROM
RETURN

ReadEEPROM:
FOR i = start to (start + finish)
READ i, LCDcharacter
GOSUB sendtoLCD
NEXT
RETURN

'[END OF SUBROUTINES]

 

Parallel Solution:

 

 '{$stamp BS2}

'[DECLARE VARIABLES]

StartScreen DATA "Lennard Electronics www.lennard.net.nz"

RS CON 8 ' Port 8, Low = Instruction to the LCD, High = Data to the LCD
RW CON 9 ' Port 9, Low = Write to the LCD, High = Read from the LCD
EnableLCD CON 10 ' Port 10, Enable LCD
character VAR BYTE
cursorposition VAR BYTE
i VAR BYTE
'Just a for loop variable

'[MAIN CODE BEGINS]
DIRS=%0000011111111111 'Set required ports (P10 - P0) as OUTPUTS
GOSUB setuplcd
GOSUB DisplayStartupMessage
END
'[END MAIN CODE]

'[ROUTINES]
setuplcd:
'Now, setup the LCD
HIGH EnableLCD
LOW RS
'sending an Instruction to the LCD
LOW RW 'Writing to the LCD
OUTl = 56 '00011100
LOW EnableLCD
PAUSE 100
'Turn the display off
HIGH EnableLCD
OUTL = 8 '00010000
LOW EnableLCD
PAUSE 100
'Turn the display on, without a cursor
HIGH EnableLCD
OUTL = 12
'00110000
LOW EnableLCD
PAUSE 100
'Clear the display
HIGH EnableLCD
OUTL = 1
'10000000
LOW EnableLCD
HIGH RS
PAUSE 1
RETURN

DisplayStartupMessage:
FOR i = 0 to 37
READ i, character
GOSUB sendtoLCD
NEXT
RETURN

newline:
'Start on next line
LOW RS
HIGH EnableLCD
OUTL = 192
LOW EnableLCD
HIGH RS
PAUSE 1
RETURN

sendtoLCD:
HIGH EnableLCD
OUTL = character
LOW EnableLCD
PAUSE 1
GOSUB cursor
RETURN

ClearDisplay:
LOW RS
HIGH EnableLCD
OUTl = 1
LOW EnableLCD
PAUSE 100
HIGH EnableLCD
'Turn the display on, with a cursor
OUTl = 13
LOW EnableLCD
PAUSE 100
HIGH RS
cursorposition = 0
RETURN

cursor:
cursorposition=cursorposition+1
IF NOT cursorposition = 20 then carryon
GOSUB newline
carryon:
RETURN

'[END OF ROUTINES]