16x2 LCD Interfacing with 8051 in 4-bit Mode:
The Assembly Code:
U EQU 31 ;memory location to hold upper nibble
L EQU 32 ;memory location to hold lower nibble
PORT EQU P1 ;data port to connect lcd
RS EQU P2.0 ;rs pin connection
RW EQU P2.1 ;rw pin connection
EN EQU P2.2 ;en pin connection
ORG 0000H
CLR RW
ACALL INIT
MOV A, #' '
ACALL LCD_DATA
MOV A, #'E' ;print " esrt. "
ACALL LCD_DATA ;in first line of lcd
MOV A, #'S'
ACALL LCD_DATA
MOV A, #'R'
ACALL LCD_DATA
MOV A, #'T'
ACALL LCD_DATA
MOV A, #'.'
ACALL LCD_DATA
MOV A, #' '
ACALL LCD_DATA
MOV A, #0C0H ;switch to 2nd line of lcd
ACALL LCD_CMD
MOV A, #' '
ACALL LCD_DATA
MOV A, #' ' ;print " lab "
ACALL LCD_DATA ;in second line of lcd
MOV A, #' '
ACALL LCD_DATA
MOV A, #' '
ACALL LCD_DATA
MOV A, #' '
ACALL LCD_DATA
MOV A, #' '
ACALL LCD_DATA
MOV A, #' '
ACALL LCD_DATA
MOV A, #'L'
ACALL LCD_DATA
MOV A, #'A'
ACALL LCD_DATA
MOV A, #'B'
ACALL LCD_DATA
MOV A, #' '
ACALL LCD_DATA
SJMP $ ;infinite long loop
; separator for upper and lower nibble
;++++++++++++++++++++++++++++++++++++++
SEPARATOR:
MOV U, A ;save a at temp location u
ANL U, #0F0H ;mask it with 0fh (28h & f0h = 20h)
SWAP A ;swap nibble (28h => 82h)
ANL A, #0F0H ;mask it with 0fh (82h & f0h = 80h)
MOV L, A ;save it at temp location l
RET ;return
; move to port sub-routine
MOVE_TO_PORT:
MOV PORT, A ;put content of a to port
SETB EN ;make en high
ACALL DELAY ;call a short delay routine
CLR EN ;clear en
ACALL DELAY ;short delay
RET ;return
; lcd command write sub-routine
LCD_CMD:
CLR RS ;clear rs, going to send command
ACALL SEPARATOR ;separate the command and save to u and l
MOV A, U ;copy u to a
ACALL MOVE_TO_PORT ;move content of a to port
MOV A, L ;copy l to a
ACALL MOVE_TO_PORT ;move content of a to port
RET ;return
; lcd data write sub-routine
LCD_DATA:
SETB RS ;rs=1, going to send data
ACALL SEPARATOR ;separate the data and save to u & l
MOV A, U ;copy u to a
ACALL MOVE_TO_PORT ;send it to lcd
MOV A, L ;copy l to a
ACALL MOVE_TO_PORT ;send it to lcd
RET ;return
;lcd initialization sub-routine
INIT:
ACALL DELAY ;some delay to lcd after power on
ACALL DELAY
MOV PORT, #20H ;send 20h to lcd to set 4 bit mode
CLR RS ;after that we can use lcd_cmd
SETB EN ;make en switching
ACALL DELAY
CLR EN
MOV A, #28H
ACALL LCD_CMD
MOV A, #0CH
ACALL LCD_CMD
MOV A, #06H
ACALL LCD_CMD
MOV A, #01H
ACALL LCD_CMD
RET
; a delay sub-routine
DELAY:
MOV R0, #10H
L2: MOV R1, #0FH
L1: DJNZ R1, L1
DJNZ R0, L2
RET
END
The code and Proteus MOdel can be downloaded from here and here