Posted on Leave a comment

LCD display on 8952 dev board

lcd 89S52 development board

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.