This example project
shows how to program an LCD Shield installed on the CGCOLORMAX.
To use Shields, the
Shield footprint is populated with female single inline sockets. Two
six-by-one and two eight-by-one headers are soldered in place on the
CGCOLORMAX so that a Shield (or a stack of them) can be added to the
board.
The LCD Shield is
actually two distinct circuits: an interface to a character-based LCD
module, and a group of five buttons that can be read
programmatically. (A sixth button is connected to the CGCOLORMAX
reset line. Be careful as this will restart the ColorMax.) There is a
line to control the LCD back light, too.
The buttons connect to
Shield line A0 which is read by MMBasic with PIN(35). This line
should be set to be an analog input. Without any buttons pressed the
input reads approximately 3.3V. Pressing the left, right, up, or down
button returns a different voltage. A function translates the
voltages to the integer values 0-4 with 0 being no button pressed.
The function created to
return the state of the buttons is below:
'
----------------------------------------------------
' Return button state
' 0 = no button
' 1 = right, 2 = up, 3 = down,
4 = left
' Because A/D on CGCOLORMAX is
3.3V max and this is a
' 5V resistor chain the SEL
button does not work.
'
----------------------------------------------------
FUNCTION LCDShield_Button( )
' Button Input line
SETPIN 35, 1
LCDShield_Button = 0
IF PIN(35) < 2.85 THEN
LCDShield_Button = 4
ENDIF
IF PIN(35) < 1.95 THEN
LCDShield_Button = 3
ENDIF
IF PIN(35) < 1.1 THEN
LCDShield_Button = 2
ENDIF
IF PIN(35) < .32 THEN
LCDShield_Button = 1
ENDIF
END FUNCTION
The LCD connects to
Shield signals D4-D9 which to MMBasic are pins 25-30. There are 4
data lines connected to communicate to the LCD as well as a line to
indicate to the LCD that you wish to send a command or a character
and a line that is a strobe for the end of data transfer. The pin
direction is set up, four bits of data (value passed to the
subroutine) are set, and the enable line pulsed. This sends a nibble
of a command to the LCD.
The function created to
send a command to the LCD is:
'
----------------------------------------------------
' Write 4-bit command
'
----------------------------------------------------
SUB LCDShield_Command4(
LCDShield_value )
' Data lines
SETPIN 25, 8 : SETPIN 26, 8 :
SETPIN 27, 8 : SETPIN 28, 8
' Register Select line
SETPIN 29, 8
' Enable line
SETPIN 30, 8
' Command (not displayable
character)
PIN(29) = 0
' Enable high
PIN(30) = 1 : PAUSE 1
' Value onto data lines
PIN(28) = LCDShield_value AND
&B00001000
PIN(27) = LCDShield_value AND
&B00000100
PIN(26) = LCDShield_value AND
&B00000010
PIN(25) = LCDShield_value AND
&B00000001
' Enable low then high
PIN(30) = 0 : PAUSE 1
PIN(30) = 1 : PAUSE 1
END SUB
To write a character so that the LCD will display it, the module needs to be told that is is not getting a command but instead something to display. Also two nibbles of data are sent to the display, first the high nibble of the character to display and then the low nibble.
'
----------------------------------------------------
' Write 8-bit character
'
----------------------------------------------------
SUB LCDShield_Character(
LCDShield_value )
' Character (not command)
PIN(29) = 1
' Enable high
PIN(30) = 1 : PAUSE 1
' Value (high nibble) onto
data lines
PIN(28) = LCDShield_value AND
&B10000000
PIN(27) = LCDShield_value AND
&B01000000
PIN(26) = LCDShield_value AND
&B00100000
PIN(25) = LCDShield_value AND
&B00010000
' Enable low then high
PIN(30) = 0 : PAUSE 1
PIN(30) = 1 : PAUSE 1
' Value (low nibble) onto
data lines
PIN(28) = LCDShield_value AND
&B00001000
PIN(27) = LCDShield_value AND
&B00000100
PIN(26) = LCDShield_value AND
&B00000010
PIN(25) = LCDShield_value AND
&B00000001
' Enable low then high
PIN(30) = 0 : PAUSE 1
PIN(30) = 1 : PAUSE 1
END SUB
A string subroutine uses the character subroutine to send a string to the display:
'
----------------------------------------------------
' Write string
'
----------------------------------------------------
SUB
LCDShield_String( LCDShield_string$ )
FOR
LCDShield_loop = 1 to LEN(LCDShield_string$)
LCDShield_Character(
ASC(MID$(LCDShield_string$, LCDShield_loop )))
NEXT
END SUB
The back light of the LCD display can be controlled by turning a line on and off:
'
----------------------------------------------------
' Backlight on/off
' 0 = off, 1 = on
'
----------------------------------------------------
SUB LCDShield_Backlight (
LCDShield_blstate )
' pin = 31
SETPIN 31, 8
PIN(31) = LCDShield_blstate
END SUB
With this library in place, some simple example code can operate the LCD.
First the LCD back
light is tested by flashing the display:
' Flash display
FOR a = 1 TO 5
LCDShield_Backlight( 0 ) :
PAUSE 40
LCDShield_Backlight( 1 ) :
PAUSE 60
NEXT a
A series of nibbles are
sent to Initialize the LCD. Four-bit (nibble) mode is selected
repeatedly to be sure, and other LCD characteristics are set. The
display is then cleared.
' Initialize display
' Select 4 bit mode
LCDShield_Command4(&H03)
LCDShield_Command4(&H03)
LCDShield_Command4(&H03)
LCDShield_Command4(&H02)
' Select 4 bit mode, two LCD
lines
LCDShield_Command4(&H02)
LCDShield_Command4(&H0C)
' Select display on, cursor
off, no blink
LCDShield_Command4(&H00)
LCDShield_Command4(&H0C)
' Clear display
LCDShield_Command4(&H00)
LCDShield_Command4(&H01)
A message to my Mom is then sent by sending each character one at a time. Then the program pauses for a second:
' Write Hi Mom! message to
line 1
LCDShield_Character(72)
LCDShield_Character(73)
LCDShield_Character(32)
LCDShield_Character(77)
LCDShield_Character(111)
LCDShield_Character(109)
LCDShield_Character(33)
PAUSE 1000
The display is then cleared:
' Clear display
LCDShield_Command4(&H00)
LCDShield_Command4(&H01)
A new message is sent to the LCD by writing a few strings.
' Write message to line 1
LCDShield_String (
"CircuitGizmos" )
' Move to line 2
LCDShield_Command4(&H0C)
LCDShield_Command4(&H00)
' Write message to line 2
LCDShield_String ( "Rules!"
)
The state of the buttons is displayed for two minutes.
FOR a = 1 TO 120
PRINT LCDShield_Button()
PAUSE 1000
NEXT a
When no button is pressed, 0 is printed. When a button is pressed the numbers 1-4 are printed.
The program in its
entirety:
'
====================================================
'
' LCDShield example
'
'
====================================================
' Flash display
for a = 1 to 5
LCDShield_Backlight( 0 ) :
PAUSE 40
LCDShield_Backlight( 1 ) :
PAUSE 60
next a
' Initialize display
' Select 4 bit mode
LCDShield_Command4(&H03)
LCDShield_Command4(&H03)
LCDShield_Command4(&H03)
LCDShield_Command4(&H02)
' Select 4 bit mode, two LCD
lines
LCDShield_Command4(&H02)
LCDShield_Command4(&H0C)
' Select display on, cursor off,
no blink
LCDShield_Command4(&H00)
LCDShield_Command4(&H0C)
' Clear display
LCDShield_Command4(&H00)
LCDShield_Command4(&H01)
' Write Hi Mom! message to line 1
LCDShield_Character(72)
LCDShield_Character(73)
LCDShield_Character(32)
LCDShield_Character(77)
LCDShield_Character(111)
LCDShield_Character(109)
LCDShield_Character(33)
PAUSE 1000
' Clear display
LCDShield_Command4(&H00)
LCDShield_Command4(&H01)
' Write message to line 1
LCDShield_String (
"CircuitGizmos" )
' Move to line 2
LCDShield_Command4(&H0C)
LCDShield_Command4(&H00)
' Write message to line 2
LCDShield_String ( "Rules!"
)
for a = 1 to 500
PRINT LCDShield_Button()
PAUSE 1000
next a
'
----------------------------------------------------
' LCDShield library
'
----------------------------------------------------
'
----------------------------------------------------
' Backlight on/off
' 0 = off, 1 = on
'
----------------------------------------------------
SUB LCDShield_Backlight (
LCDShield_blstate )
' pin = 31
SETPIN 31, 8
PIN(31) = LCDShield_blstate
END SUB
'
----------------------------------------------------
' Write 4-bit command
'
----------------------------------------------------
SUB LCDShield_Command4(
LCDShield_value )
' Data lines
SETPIN 25, 8 : SETPIN 26, 8 :
SETPIN 27, 8 : SETPIN 28, 8
' Register Select line
SETPIN 29, 8
' Enable line
SETPIN 30, 8
' Command
PIN(29) = 0
' Enable high
PIN(30) = 1 : PAUSE 1
' Value onto data lines
PIN(28) = LCDShield_value AND
&B00001000
PIN(27) = LCDShield_value AND
&B00000100
PIN(26) = LCDShield_value AND
&B00000010
PIN(25) = LCDShield_value AND
&B00000001
' Enable low then high
PIN(30) = 0 : PAUSE 1
PIN(30) = 1 : PAUSE 1
END SUB
'
----------------------------------------------------
' Write 8-bit character
'
----------------------------------------------------
SUB LCDShield_Character(
LCDShield_value )
' Character
PIN(29) = 1
' Enable high
PIN(30) = 1 : PAUSE 1
' Value (high nibble) onto
data lines
PIN(28) = LCDShield_value AND
&B10000000
PIN(27) = LCDShield_value AND
&B01000000
PIN(26) = LCDShield_value AND
&B00100000
PIN(25) = LCDShield_value AND
&B00010000
' Enable low then high
PIN(30) = 0 : PAUSE 1
PIN(30) = 1 : PAUSE 1
' Value (low nibble) onto
data lines
PIN(28) = LCDShield_value AND
&B00001000
PIN(27) = LCDShield_value AND
&B00000100
PIN(26) = LCDShield_value AND
&B00000010
PIN(25) = LCDShield_value AND
&B00000001
' Enable low then high
PIN(30) = 0 : PAUSE 1
PIN(30) = 1 : PAUSE 1
END SUB
'
----------------------------------------------------
' Write string
'
----------------------------------------------------
SUB LCDShield_String(
LCDShield_string$ )
FOR LCDShield_loop = 1 to
LEN(LCDShield_string$)
LCDShield_Character(
ASC(MID$(LCDShield_string$, LCDShield_loop )))
NEXT
END SUB
'
----------------------------------------------------
' Return button state
' 0 = no button
' 1 = right, 2 = up, 3 = down, 4
= left
' Because A/D on CGCOLORMAX is
3.3V max and this is a
' 5V resistor chain the SEL
button does not work.
'
----------------------------------------------------
FUNCTION LCDShield_Button( )
' Button Input line
SETPIN 35, 1
LCDShield_Button = 0
IF PIN(35) < 2.85 THEN
LCDShield_Button = 4
ENDIF
IF PIN(35) < 1.95 THEN
LCDShield_Button = 3
ENDIF
IF PIN(35) < 1.1 THEN
LCDShield_Button = 2
ENDIF
IF PIN(35) < .32 THEN
LCDShield_Button = 1
ENDIF
END FUNCTION