# 8051 LCD interfacing works in Proteous but doesn't work in hardware

I'm working on this project using an 8051 micro controller (AT89S51) and it involves interfacting with an LCD. The schematic of the project I'm working on is shown below:

And I've written a very simple code for the LCD to display content. The code is as follows:

ORG 0000H
SJMP INIT_MAIN          ;For interrupts

INIT_MAIN:
;Initializing the LCD Display with the initial commands:
MOV A, #38H       ;Setting up the LCD to operate in 8 bit mode
ACALL CMD
MOV A, #0FH       ;Turning the display on
ACALL CMD
MOV A, #01H       ;Clearing the curser
ACALL CMD
MOV A, #06H       ;Putting the curser incriment mode to be left to right
ACALL CMD
MOV A, #3CH       ;Activating the second line of the LCD
ACALL CMD
MOV A, #80H       ;Putting the curser to be at position 1 (the first place)
ACALL CMD

;Writing serially on the LCD
MOV DPTR, #WELCOME1   ;Pointing the data pointer at the data array WELCOME1
MOV 41H, #13H     ;Specifying the message's length
LCALL LCD_SERIAL      ;Giving the command to the uC to print it on the LCD

ACALL CMD

MOV DPTR, #WELCOME2   ;Pointing the data pointer at the data array WELCOME1
MOV 41H, #13H     ;Specifying the message's length
LCALL LCD_SERIAL      ;Giving the command to the uC to print it on the LCD

ACALL CMD

MOV DPTR, #WELCOME3   ;Pointing the data pointer at the data array WELCOME1
MOV 41H, #13H     ;Specifying the message's length
LCALL LCD_SERIAL      ;Giving the command to the uC to print it on the LCD

ACALL CMD

MOV DPTR, #WELCOME4   ;Pointing the data pointer at the data array WELCOME1
MOV 41H, #10H     ;Specifying the message's length
LCALL LCD_SERIAL      ;Giving the command to the uC to print it on the LCD

MOV A, #0FFH      ;Pointing the curser away from the screen
ACALL CMD

MAIN:
SJMP MAIN
;-------------------------------------DELAY SUBROUTINES-------------------------------------
DELAY_1ms:          ;delay for 1ms subroutine
MOV 39H,#0FAH         ;Load 0FA into the register 39H
MOV 40H,#0FAH     ;Load 0FA into the register 40H
LABEL1: DJNZ 39H,LABEL1   ;Decrease 39H by one and jump if not zero
LABEL2: DJNZ 40H,LABEL2   ;Decrease 40H by one and jump if not zero
RET

;-------------------------------------LCD SUBROUTINES---------------------------------------
CMD:                    ;Commands used in intializations
MOV P1, A         ;Move the values of A to Pin 1. These will be the commands we want to transfer
CLR P3.5          ;This makes the RS equal to 0. When RS is zero,
CLR P3.6          ;This makes the RW equal to 0. When RW is zero,
SETB P3.7         ;This control the latch. Setting it and resetting it, latches the data
CLR P3.7          ;This control the latch. Setting it and resetting it, latches the data
ACALL DELAY_1ms   ;A delay is required because on practical LCDs, it takes some time to change
RET

LCD_SERIAL:             ;Used to display strings onto the LCD
MOV R0, #00H
REPEAT:
MOV A,R0
MOVC A,@A+DPTR        ;obtain LCD lookup table
ACALL LCD_DISPLAY     ;Display the character on the screen
INC R0                ;Increment R0
DJNZ 41H, REPEAT
RET

LCD_DISPLAY:            ;Used to display info onto the LCD
MOV P1, A         ;Move the values of A to pin 1. The data will now be on Port 1
SETB P3.5         ;This makes RS equal to 1. When RS is one,
CLR P3.6          ;This makes the RW equal to 0. When RW is one,
SETB P3.7         ;This control the latch. Setting it and resetting it, latches the data
CLR P3.7          ;This control the latch. Setting it and resetting it, latches the data
ACALL DELAY_1ms       ;A delay is required because on practical LCDs, it takes some time to change
RET

;--------------------------------------LOOK UP TABLES---------------------------------------
WELCOME1:
DB 'WELCOME TO THE BANK'

WELCOME2:
DB 'PREVIOUS NUMBER 000'

WELCOME3:

WELCOME4:
DB 'HAVE A GOOD DAY!'

END


The above code is not the full code that I've written, but only the portions relevant to the LCD display.

This code works fine in the proteous simulation (as can be seen from the picture). However, it doesn't work at all when I construct it on a real circuit. Sometimes the LCD backlight would just turn on and nothing would be shown (not even black squares) even if I adjust the potentiometer. Sometimes, the black squares would show, but upon resetting the 8051 they'd disappear.

In case it matters, the programmer I'm using is the MikroE 8051 programmer,

I've done the following yesterday while constructing the circuit:

1. Made sure that all of my jumpers were indeed conducting by checking them on an LED first.
2. Tried this code with multiple LCD displays, none of them worked
3. Tried this code on another 8051 chip, it still didn't work
4. Got a sample code online of someone interfacing a 8051 with an LCD and my LCDs still didn't work

I would greatly appreciate it if someone could give me an insight on why this could be the case