- This library can drive all HD44780 LCD's of any configuration up to 40 characters x 4 lines, including dual LCD configurations. It is primarily designed for easy printing to a 40x4 LCD. By using the LCD440_OUT() and LCD440_CHR() commands, the programmer can simply state the line and position to start printing without any address calculations or manual controller changes.
The following LCD440 Source Code is actually 2 different libraries, one for P16 PIC's, and the other for P18 PIC's. Install the correct one in the same folder as your program and compile using the INCLUDE directive in your main program or another module:
For P16:For P18:Code: Select all
program myprog include "lcd440_p16"
The prototypes are almost identical to the other mBASIC LCD routines. You can use all the same commands which are compatible with the HD44780 LCD controller. A couple differences to note is LCD440_CMD() and LCD440_CONFIG(). LCD440_CMD() requires a controller value, 1 or 2, in addition to the command byte. LCD440_CONFIG() requires that you choose the upper or lower 4 bits of the PORT used for the data lines. $0F or "LoNyb" are values that can be used for the lower nybble, and $F0 or "HiNyb" can be used for the high nybble.Code: Select all
program myprog include "lcd440_p18"
- LCD440_CONFIG(dim byref dataport as byte, dim nybble as byte, dim byref controlport as byte, dim rs, e1, e2 as byte)
- Example: LCD440_CONFIG(PortB, HiNyb, PortC, 5, 0, 1)
Comments: HiNyb and LoNyb are constants equal to $F0 and $0F, respectively. The data lines D7..D4 should be connected to PORTx<7..4> for the upper nybble, or PORTx<3..0> for the lower nybble.
- Example: LCD440_CMD(1, LCD_CURSOR_OFF)
Comments: Valid controller values are 1 and 2.
- Example: LCD440_OUT(1, 4, "xor was here")
Example: LCD440_OUT(4, 21, text)
Comments: Valid Row values are 1 thru 4, and valid Column values are 1 thru 40. The maximum string length is 40 characters.
- Example: LCD440_CHR(2, 12, "A")
Example: LCD440_CHR(3, 1, 65)
Comments: Valid Row values are 1 thru 4, and valid Column values are 1 thru 40. Maximum of one character or byte.
- Example: LCD440_OUT_CP("Stop Here")
Example: LCD440_OUT_CP(mystring)
Comments: The maximum string length is 40 characters.
- Example: LCD440_CHR_CP("Hello")
Example: LCD440_CHR_CP(mybyte)
Comments: Maximum of one character or byte.
- Example: LCD440_CONFIG(PortB, HiNyb, PortC, 5, 0, 1)
- LCD440_CONFIG(dim byref dataport as byte, dim nybble as byte, dim byref controlport as byte, dim rs, e1, e2 as byte)
Code: Select all
module LCD440_P16
include "lcd_consts"
include "delays"
const HiNyb as byte = $F0
const LoNyb as byte = $0F
dim dport, cport as ^byte
dim _rs, _e1, _e2, _cc, dmask as byte
implements
sub procedure delay_40us
delay_us(40)
end sub
sub procedure CLOCKIN(dim cont as byte) ' takes E1 or E2 high then low
dim t0 as byte
If cont = 1 Then
t0 = _e1
Else
t0 = _e2
End If
cport^ = cport^ Or t0
delay_1us
cport^ = cport^ And Not(t0)
end sub
'****************************************************************************************
' **** LCD440_CMD accepts CONTROLLER VALUE (1 or 2), COMMAND BYTE ****
'****************************************************************************************
sub procedure LCD440_CMD(dim controller, cmd as byte) ' must pass the controller# (1 or 2) & byte
dim t as byte[2]
_cc = controller
If dmask = $0F Then
t[0] = $F0 And cmd ' get high nybble and store high
t[1] = cmd << 4 ' get low nybble and store high
Else
t[0] = cmd >> 4 ' get high nybble and store low
t[1] = $0F and cmd ' get low nybble and store low
End If
dport^ = (dport^ And dmask) Or t[0] ' clear dataport and output cmd high nybble
CLOCKIN(controller)
dport^ = (dport^ And dmask) Or t[1] ' clear dataport and output cmd low nybble
CLOCKIN(controller)
If cmd > 2 Then
delay_40us ' this delay is required for most commands
Else
delay_5500us ' this delay is for LCD_CLEAR & LCD_CURSOR_HOME
End If
end sub
'****************************************************************************************
' **** LCD440_CONFIG accepts DATAPORT, HiNyb or LoNyb, CONTROLPORT, RS, E1, & E2 ****
'****************************************************************************************
sub procedure LCD440_CONFIG(dim byref dataport as byte,
dim nybble as byte,
dim byref controlport as byte,
dim rs, e1, e2 as byte)
dim cmask as byte
'**** setup global variables ****
_rs = 1 << rs
_e1 = 1 << e1
_e2 = 1 << e2
dmask = Not(nybble)
cmask = 255
clearbit(cmask, rs)
clearbit(cmask, e1)
clearbit(cmask, e2)
dport = @dataport
cport = @controlport
'**** clear data lines & do TRIS setup ****
dport^ = dport^ And dmask ' clear data lines
setbit(dport, 7) ' for P18's: dport = dport + 18
dport^ = dport^ And dmask ' TRIS data lines as outputs
clearbit(dport, 7) ' for P18's: dport = dport - 18
'**** clear control lines & do TRIS setup ****
cport^ = cport^ And cmask ' clear control lines
setbit(cport, 7) ' for P18's: cport = cport + 18
cport^ = cport^ And cmask ' TRIS control lines as outputs
clearbit(cport, 7) ' for P18's: cport = cport - 18
'**** intialize the LCD ****
delay_5500us ' min 15ms delay at LCD powerup
delay_5500us
delay_5500us
dport^ = dport^ Or (nybble And $33) ' clock-in $03 3 times with min 5ms, 160us, & 160us delays
CLOCKIN(1)
CLOCKIN(2)
delay_5500us
CLOCKIN(1)
CLOCKIN(2)
delay_40us
delay_40us
delay_40us
delay_40us
CLOCKIN(1)
CLOCKIN(2)
delay_40us
delay_40us
delay_40us
delay_40us
dport^ = dport^ And dmask ' clear data
dport^ = dport^ Or (nybble And $22) ' clock-in $02 for 4-bit mode
CLOCKIN(1)
CLOCKIN(2)
LCD440_CMD(1, $28) ' set for 2-line
LCD440_CMD(2, $28)
LCD440_CMD(1, $10) ' turn display off
LCD440_CMD(2, $10) ' turn display off
LCD440_CMD(1, $01) ' clear display
LCD440_CMD(2, $01) ' clear display
LCD440_CMD(1, $14) ' set cursor direction
LCD440_CMD(2, $14) ' set cursor direction
LCD440_CMD(1, $0F) ' turn display on, cursor on, blink on
LCD440_CMD(2, $0F) ' turn display on, cursor on, blink on
_cc = 1 ' current controller is 1
end sub
'****************************************************************************************
' **** LCD440_OUT accepts Row Value, Column Value, and a string up to 40 character ****
'****************************************************************************************
sub procedure LCD440_OUT(dim row, column as byte, dim byref _string as string[40])
dim cp, c0, tmp as byte
dec(column)
Select Case row ' determine controller and cursor position
Case 1
cp = 128
c0 = 1
Case 2
cp = 192
c0 = 1
Case 3
cp = 128
c0 = 2
Case 4
cp = 192
c0 = 2
End Select
LCD440_CMD(c0, cp + column) ' set the cursor position
cport^ = cport^ Or _rs ' set RS for LCD text
tmp = 0
While _string[tmp] <> 0 ' send string...stop at end of string
LCD440_CMD(c0, _string[tmp]) ' print character at cursor position and auto-increment position
inc(tmp) ' next character in string
Wend
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
'****************************************************************************************
' **** LCD440_CHR accepts a ROW VALUE, COLUMN VALUE, and a single character ****
'****************************************************************************************
sub procedure LCD440_CHR(dim row, column as byte, dim _character as char)
dim cp, c0, tmp as byte
dec(column)
Select Case row ' determine controller and cursor position
Case 1
cp = 128
c0 = 1
Case 2
cp = 192
c0 = 1
Case 3
cp = 128
c0 = 2
Case 4
cp = 192
c0 = 2
End Select
LCD440_CMD(c0, cp + column) ' set cursor position
cport^ = cport^ Or _rs ' set RS for LCD text
LCD440_CMD(c0, _character) ' print character at cursor position and auto-increment position
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
'**************************************************************************************************
'**** LCD440_OUT_CP accepts a string up to 40 character and print to current cursor position ****
'**************************************************************************************************
sub procedure LCD440_OUT_CP(dim byref _string as string[40])
dim tmp as byte
cport^ = cport^ Or _rs ' set RS for LCD text
tmp = 0
While _string[tmp] <> 0 ' send string...stop at end of string
LCD440_CMD(_cc, _string[tmp]) ' print character at cursor position and auto-increment position
inc(tmp) ' next character in string
Wend
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
'**************************************************************************************************
' **** LCD440_CHR_CP accepts a single character and prints at the current cursor position ****
'**************************************************************************************************
sub procedure LCD440_CHR_CP(dim _character as char)
cport^ = cport^ Or _rs ' set RS for LCD text
LCD440_CMD(_cc, _character) ' print character at cursor position and auto-increment position
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
end.
Code: Select all
module LCD440_P18
include "lcd_consts"
include "delays"
const HiNyb as byte = $F0
const LoNyb as byte = $0F
dim dport, cport as ^byte
dim _rs, _e1, _e2, _cc, dmask as byte
implements
sub procedure delay_40us
delay_us(40)
end sub
sub procedure CLOCKIN(dim cont as byte) ' takes E1 or E2 high then low
dim t0 as byte
If cont = 1 Then
t0 = _e1
Else
t0 = _e2
End If
cport^ = cport^ Or t0
delay_1us
cport^ = cport^ And Not(t0)
end sub
'****************************************************************************************
' **** LCD440_CMD accepts CONTROLLER VALUE (1 or 2), COMMAND BYTE ****
'****************************************************************************************
sub procedure LCD440_CMD(dim controller, cmd as byte) ' must pass the controller# (1 or 2) & byte
dim t as byte[2]
_cc = controller
If dmask = $0F Then
t[0] = $F0 And cmd ' get high nybble and store high
t[1] = cmd << 4 ' get low nybble and store high
Else
t[0] = cmd >> 4 ' get high nybble and store low
t[1] = $0F and cmd ' get low nybble and store low
End If
dport^ = (dport^ And dmask) Or t[0] ' clear dataport and output cmd high nybble
CLOCKIN(controller)
dport^ = (dport^ And dmask) Or t[1] ' clear dataport and output cmd low nybble
CLOCKIN(controller)
If cmd > 2 Then
delay_40us ' this delay is required for most commands
Else
delay_5500us ' this delay is for LCD_CLEAR & LCD_CURSOR_HOME
End If
end sub
'****************************************************************************************
' **** LCD440_CONFIG accepts DATAPORT, HiNyb or LoNyb, CONTROLPORT, RS, E1, & E2 ****
'****************************************************************************************
sub procedure LCD440_CONFIG(dim byref dataport as byte,
dim nybble as byte,
dim byref controlport as byte,
dim rs, e1, e2 as byte)
dim cmask as byte
'**** setup global variables ****
_rs = 1 << rs
_e1 = 1 << e1
_e2 = 1 << e2
dmask = Not(nybble)
cmask = 255
clearbit(cmask, rs)
clearbit(cmask, e1)
clearbit(cmask, e2)
dport = @dataport
cport = @controlport
'**** clear data lines & do TRIS setup ****
dport^ = dport^ And dmask ' clears data lines
dport = dport + 18 ' for P16's: setbit(dport, 7)
dport^ = dport^ And dmask ' TRIS data lines as outputs
dport = dport - 18 ' for P16's: clearbit(dport, 7)
'**** clear control lines & do TRIS setup ****
cport^ = cport^ And cmask ' clears control lines
cport = cport + 18 ' for P16's: setbit(cport, 7)
cport^ = cport^ And cmask ' TRIS control lines as outputs
cport = cport - 18 ' for P16's: clearbit(cport, 7)
'**** intialize the LCD ****
delay_5500us ' min 15ms delay at LCD powerup
delay_5500us
delay_5500us
dport^ = dport^ Or (nybble And $33) ' clock-in $03 3 times with min 5ms, 160us, & 160us delays
CLOCKIN(1)
CLOCKIN(2)
delay_5500us
CLOCKIN(1)
CLOCKIN(2)
delay_40us
delay_40us
delay_40us
delay_40us
CLOCKIN(1)
CLOCKIN(2)
delay_40us
delay_40us
delay_40us
delay_40us
dport^ = dport^ And dmask ' clear data
dport^ = dport^ Or (nybble And $22) ' clock-in $02 for 4-bit mode
CLOCKIN(1)
CLOCKIN(2)
LCD440_CMD(1, $28) ' set for 2-line
LCD440_CMD(2, $28)
LCD440_CMD(1, $10) ' turn display off
LCD440_CMD(2, $10) ' turn display off
LCD440_CMD(1, $01) ' clear display
LCD440_CMD(2, $01) ' clear display
LCD440_CMD(1, $14) ' set cursor direction
LCD440_CMD(2, $14) ' set cursor direction
LCD440_CMD(1, $0F) ' turn display on, cursor on, blink on
LCD440_CMD(2, $0F) ' turn display on, cursor on, blink on
_cc = 1 ' current controller is 1
end sub
'****************************************************************************************
' **** LCD440_OUT accepts Row Value, Column Value, and a string up to 40 character ****
'****************************************************************************************
sub procedure LCD440_OUT(dim row, column as byte, dim byref _string as string[40])
dim cp, c0, tmp as byte
dec(column)
Select Case row ' determine controller and cursor position
Case 1
cp = 128
c0 = 1
Case 2
cp = 192
c0 = 1
Case 3
cp = 128
c0 = 2
Case 4
cp = 192
c0 = 2
End Select
LCD440_CMD(c0, cp + column) ' set the cursor position
cport^ = cport^ Or _rs ' set RS for LCD text
tmp = 0
While _string[tmp] <> 0 ' send string...stop at end of string
LCD440_CMD(c0, _string[tmp]) ' print character at cursor position and auto-increment position
inc(tmp) ' next character in string
Wend
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
'****************************************************************************************
' **** LCD440_CHR accepts a ROW VALUE, COLUMN VALUE, and a single character ****
'****************************************************************************************
sub procedure LCD440_CHR(dim row, column as byte, dim _character as char)
dim cp, c0, tmp as byte
dec(column)
Select Case row ' determine controller and cursor position
Case 1
cp = 128
c0 = 1
Case 2
cp = 192
c0 = 1
Case 3
cp = 128
c0 = 2
Case 4
cp = 192
c0 = 2
End Select
LCD440_CMD(c0, cp + column) ' set cursor position
cport^ = cport^ Or _rs ' set RS for LCD text
LCD440_CMD(c0, _character) ' print character at cursor position and auto-increment position
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
'**************************************************************************************************
'**** LCD440_OUT_CP accepts a string up to 40 character and print to current cursor position ****
'**************************************************************************************************
sub procedure LCD440_OUT_CP(dim byref _string as string[40])
dim tmp as byte
cport^ = cport^ Or _rs ' set RS for LCD text
tmp = 0
While _string[tmp] <> 0 ' send string...stop at end of string
LCD440_CMD(_cc, _string[tmp]) ' print character at cursor position and auto-increment position
inc(tmp) ' next character in string
Wend
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
'**************************************************************************************************
' **** LCD440_CHR_CP accepts a single character and prints at the current cursor position ****
'**************************************************************************************************
sub procedure LCD440_CHR_CP(dim _character as char)
cport^ = cport^ Or _rs ' set RS for LCD text
LCD440_CMD(_cc, _character) ' print character at cursor position and auto-increment position
cport^ = cport^ And Not(_rs) ' reset RS for LCD commands
end sub
end.