
I have a cheap 8952 dev board from China and I added a Arduino Nano as ISP programmer to it so I can upload the code easily. This works fine but the dev board is a little limited in I/O, it only has a few buttons and eight led. There is a connector for a 1602 LCD display, but no supporting code. So I took up the challenge of making this myself. On this page you can find the 8051 assembly code of a simple LCD driver using the HD44780 type of driver. I have written code for this driver in the past so it wasn’t a complete surprise. The connections are quite obvious, I put them as equates in the beginning of the code so you can easily switch them to other pins on your design.
; ---------------------------------------
; 8052 LCD interface
; Hein Pragt 2023
; ---------------------------------------
// commands
LCD_CLEARDISPLAY equ 01H
LCD_RETURNHOME equ 02H
LCD_ENTRYMODESET equ 04H
LCD_DISPLAYCONTROL equ 08H
LCD_CURSORSHIFT equ 10H
LCD_FUNCTIONSET equ 20H
LCD_SETCGRAMADDR equ 40H
LCD_SETDDRAMADDR equ 80H
// flags for display entry mode
LCD_ENTRYRIGHT equ 00H
LCD_ENTRYLEFT equ 02H
LCD_ENTRYSHIFTINCREMENT equ 01H
LCD_ENTRYSHIFTDECREMENT equ 00H
// flags for display on/off control
LCD_DISPLAYON equ 04H
LCD_DISPLAYOFF equ 00H
LCD_CURSORON equ 02H
LCD_CURSOROFF equ 00H
LCD_BLINKON equ 01H
LCD_BLINKOFF equ 00H
// flags for display/cursor shift
LCD_DISPLAYMOVE equ 08H
LCD_CURSORMOVE equ 00H
LCD_MOVERIGHT equ 04H
LCD_MOVELEFT equ 00H
// flags for function set
LCD_8BITMODE equ 10H
LCD_4BITMODE equ 00H
LCD_2LINE equ 08H
LCD_1LINE equ 00H
LCD_5x10DOTS equ 04H
LCD_5x8DOTS equ 00H
EN_PIN equ p1.0
RW_PIN equ P1.1
RS_PIN equ P1.2
LCD_DATA equ P2
CSEG
ORG 0000H
call lcd_init
call lcd_home
;
mov a,#0
mov b,#3
call lcd_pos
;
mov dptr,#hello
call lcd_print
mov a,#1
mov b,#3
call lcd_pos
mov dptr,#hein
call lcd_print
loop:
jmp loop
hello:
db 'Hello World',0
hein:
db 'Hein Pragt',0
; -------------------
; Init LCD display in 8 bit mode
; -------------------
lcd_init:
clr EN_PIN
clr RW_PIN
clr RS_PIN
mov a,#0
mov LCD_DATA,a ; Data, RS and R/W low
mov r6,#15
call delay ; Delay 15 Ms
;
mov a,#(LCD_FUNCTIONSET + LCD_8BITMODE + LCD_2LINE)
call lcd_command
mov r6,#5
call delay ; Delay 5 Ms
;
mov a,#(LCD_FUNCTIONSET + LCD_8BITMODE + LCD_2LINE)
call lcd_command
call delay1ms ; Delay 1 ms
;
mov a,#(LCD_FUNCTIONSET + LCD_8BITMODE + LCD_2LINE)
call lcd_command
call delay1ms ; Delay 1 ms
mov a,#(LCD_FUNCTIONSET + LCD_8BITMODE + LCD_2LINE)
call lcd_command
;
mov a,#(LCD_DISPLAYCONTROL + LCD_DISPLAYON + LCD_CURSOROFF + LCD_BLINKOFF);
call lcd_command
mov a,#(LCD_ENTRYMODESET + LCD_ENTRYLEFT + LCD_ENTRYSHIFTDECREMENT)
call lcd_command
call lcd_clear
ret
; -------------------
; Send CLS command to LCD
; -------------------
lcd_clear:
mov a,#LCD_CLEARDISPLAY
call lcd_command;
mov r6,#50
call delay ; Delay 50 ms
ret
; -------------------
; Send Home command to LCD
; -------------------
lcd_home:
mov a,#LCD_RETURNHOME
call lcd_command;
mov r6,#50
call delay ; Delay 50 ms
ret
; -------------------
; Send cursor
; a = row 0,1 b = col 0.16
; -------------------
lcd_pos:
anl a,#01H
jz row0
mov a,#40H ; row1
row0:
orl a,#LCD_SETDDRAMADDR
anl b,#0fH
orl a,b
call lcd_command;
mov r6,#50
call delay ; Delay 50 ms
ret
; -------------------
; Print 0 tyerm string in DPTR
; -------------------
lcd_print:
clr a
movc a,@a+dptr ; Read char
inc dptr ; Bump pointer.
jz prt_end
;
call lcd_char ; print char
ajmp lcd_print ; Loop
prt_end:
ret
; -------------------
; Send char to LCD
; char is in A
; -------------------
lcd_char:
clr RW_PIN
setb RS_PIN
clr EN_PIN
setb EN_PIN
mov LCD_DATA,a
clr EN_PIN
setb RW_PIN
clr RS_PIN
acall delay1ms
ret
; -------------------
; Send command to LCD
; command is in A
; -------------------
lcd_command:
clr RW_PIN
clr RS_PIN
clr EN_PIN
setb EN_PIN
mov LCD_DATA,a
clr EN_PIN
setb RW_PIN
acall delay1ms
ret
; =======================================
; General subroutines
; =======================================
; -------------------
; Delay R6 x 1 Ms
; -------------------
delay:
call delay1ms
djnz R6,delay
ret
; -------------------
; Delay 1 ms
; -------------------
delay1ms:
mov TMOD,#01H ; Mode 1
mov TH0,#0FCH
mov TL0,#018H
clr TF0
setb TR0
dellp1:
jnb TF0,dellp1
;
clr TR0
clr TF0
ret
END
Yo can download the code here: Download lcd_display.zip

I hope this is useful and inspires you to add new features, or use it in one of your own project, for me it was fun to write 8051 assembly code again.