Skip to main content

LCD Interfacing with 8051 in 4 bit mode : assembly tutorial

Hello friends, in this tutorial we are going to interface LCD with 8051 microcontroller but in 4 bit mode. we already interfaced LCD with 8051 in 8 bit and also done scrolling of text in previous tutorials.











if you already know how to interface LCD with microcontroller in 8 bit mode then it is not difficult to interface LCD in 4 bit mode. but if you don't know how to interface LCD with 8051 microcontroller in 8 bit mode than read these points.
  • First we initialize LCD by sending different command
  • To send command we make RS=0[low] and put command on DATA pins of LCD(DB0-BD7)
  • Then make EN = 1[high] and after some delay EN = 0[low]. it make a high to low pulse on EN of LCD
  • Do same thing to send data but this time RS = 1[high]
  • this is called LCD interfacing in 8 bit mode
But in 4 bit interfacing mode that we only use 4 data lines [DB4-DB7] of LCD. As we are going to use only 4 data lines so we need to send data in group of 4 bits ( called nibble). The Higher nibble is send first and then lower nibble is send. In this program i use two memory location to store my upper and lower nibble after separating a 8 bit data.

This is how i connect LCD and other variables

  U equ 31H        ;memory location to hold upper nibble
  L equ 32H  ;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

  ;connection of Port
  ;Port.1-Port.3 (not used)
  ;Port.4 = DB4
  ;Port.5 = DB5
  ;Port.6 = DB6
  ;Port.7 = DB7

How i send Data and Command

As you can see from connection of LCD and microcontroller that i can send data to LCD in the upper nibble of the port only because lower nibble is not connected. so if i need to send 02H (Two) then i have to send it as 20h. by doing this LCD read only upper nibble of port that is 2.
And if i need to send 28h then i send first 20h and then 80h.(upper nibble first and lower nibble second).

How to Break 8 bit Data

4 bit LCD interfacing mode require that we first break 8 bit data in to 4 bit data and then send it to LCD.
Let we have 28h in accumulator register and we are going to send it to LCD. So we need to break it. We can break it as 20h (higher nibble) and 80h (lower nibble).
 If i perform AND operation of 28h with F0h then it become 20H (upper nibble) and if i swap nibbles of 28h (become 82h) and then do same ANDing then i got 80H (lower nibble).
We can write a routine to perform separation because it needed when we send command and data to LCD. lets call it Separator.i use two memory location to store to upper(U) nibble and lower nibble(L). it will make the program simple and better understandable.
  ++++++++++++++++++++++++++++++++++++++++++++++++++++
  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 Data/Command to LCD

i write many routine so the code become simpler because long code is easy to understand than shorter and compact one. but you can put all in single routine.
Let make a routine which put data/command on Port and make EN Switching (high to low). this routine not going to tell LCD that it is a command or Data. it only put to LCD whatever you give it.
  ++++++++++++++++++++++++++++++++++++++++++++++++++++
  move_to_Port:
   MOV port,A       ;put content of A to port
   SETB EN   ;make EN hight
   ACALL DELAY   ;call a short delay routine
   CLR EN    ;clear EN
   ACALL DELAY   ;short delay
   RET     ;return
  +++++++++++++++++++++++++++++++++++++++++++++++++++++
 

Send Command to LCD

Now i need to send command to LCD. if i set rs=0 and send data then LCD consider it as command. let call it lcd_cmd
   +++++++++++++++++++++++++++++++++++++++++++++++++++++
   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
   +++++++++++++++++++++++++++++++++++++++++++++++++++++
  
now you can send command easily to LCD. you only need put command in A and call lcd_cmd.

Send Data to LCD

Routine to send data to LCD remain same as to send command. the only thing change that this time RS will be High.
  +++++++++++++++++++++++++++++++++++++++++++++++++++++
  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
  +++++++++++++++++++++++++++++++++++++++++++++++++++++
 

The Delay

Delay have a great role in LCD interfacing with 8051 microcontroller. Because processing speed of LCD and 8051 is not same. And LCD need some time to process the command, and 8051 have to wait. if the delay is not proper and you give command to LCD then LCD will not receive it because it is busy in doing some thing else. let make a short delay routine.
  +++++++++++++++++++++++++++++++++++++++++++++++++++++
  delay:
   MOV R0, #10H
  L2: MOV R1,#0FH
  L1: DJNZ R1, L1
   DJNZ R0, L2
   RET
  +++++++++++++++++++++++++++++++++++++++++++++++++++++
 
you can change the value of delay i take it randomly. check datasheet for precise delay.

Ready to launch the Rocket

OK we have all the routine and function. now we only need to initialize the LCD by sending some command and then we can send the data bytes.
Here is Pin description of LCD and instruction

pin description of the 16x2 LCD

command list of LCD and 8051 interfacing

Initialization

Before sending any thing to LCD first i need to tell LCD that i am going to interface in 4 bit mode. to do this i first send 20h on the port and make switching of EN. all commands are-
  1. Send 20h to set 4 bit mode
  2. Send 28h to set 4 bit Interface,2 Line LCD, and 5x7 Font set,
  3. Send 0ch to set Display ON, Cursor OFF and Blink ON
  4. Send 06h to set Cursor Position Auto Increment and Cursor Move to Right
  5. Send 01h to Clear the display and bring cursor to starting location
  +++++++++++++++++++++++++++++++++++++++++++++++++++++
  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
  +++++++++++++++++++++++++++++++++++++++++++++++++++++

 

Here is full program to interface LCD with 8051 in 4 bit mode

  $mod51
;+++++++++++++++++++++++++++variables
;++++++++++++++++++++++++++++++++++++

  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

  ;connection of Port
  ;Port.1-Port.3 (not used)
  ;Port.4 = DB4
  ;Port.5 = DB5
  ;Port.6 = DB6
  ;Port.7 = DB7
;+++++++++++++++++++++++++++++++++++++
  ORG 0000h
  CLR RW
  ACALL init

  MOV A, #'T'     ;SEND "TENTUTS.COM 4BIT" 
  ACALL lcd_data     ;in first line of LCD
  MOV A, #'E'
  ACALL lcd_data
  MOV A, #'N'
  ACALL lcd_data
  MOV A, #'T'
  ACALL lcd_data
  MOV A, #'U'
  ACALL lcd_data
  MOV A, #'T'
  ACALL lcd_data
  MOV A, #'S'
  ACALL lcd_data
  MOV A, #'.'
  ACALL lcd_data
  MOV A, #'C'
  ACALL lcd_data
  MOV A, #'O'
  ACALL lcd_data
  MOV A, #'M'
  ACALL lcd_data
  MOV A, #' '
  ACALL lcd_data
  MOV A, #'4'
  ACALL lcd_data
  MOV A, #'B'
  ACALL lcd_data
  MOV A, #'I'
  ACALL lcd_data
  MOV A, #'T'
  ACALL lcd_data

  MOV A, #0c0H         ;switch to 2nd line of LCD
  ACALL lcd_cmd  

  MOV A, #'M'     ;SEND "MODE USING 2 PORT" 
  ACALL lcd_data     ;in SECOND line of LCD
  MOV A, #'O'
  ACALL lcd_data
  MOV A, #'D'
  ACALL lcd_data
  MOV A, #'E'
  ACALL lcd_data
  MOV A, #' '
  ACALL lcd_data
  MOV A, #'U'
  ACALL lcd_data
  MOV A, #'S'
  ACALL lcd_data
  MOV A, #'I'
  ACALL lcd_data
  MOV A, #'N'
  ACALL lcd_data
  MOV A, #'G'
  ACALL lcd_data
  MOV A, #' '
  ACALL lcd_data
  MOV A, #'2'
  ACALL lcd_data
  MOV A, #'P'
  ACALL lcd_data
  MOV A, #'O'
  ACALL lcd_data
  MOV A, #'R'
  ACALL lcd_data
  MOV A, #'T'
  ACALL lcd_data
  
  SJMP $     ;INFINITE LONG LOOP

;+++++++++++++++++++++++++++++Separator
;++++++++++++++++++++++++++++++++++++++

 
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 
;++++++++++++++++++++++++++++++++++++++

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 
;++++++++++++++++++++++++++++++++++++++

   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
;++++++++++++++++++++++++++++++++++++++

  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

;+++++++++++++++++++++++++Initilization
;++++++++++++++++++++++++++++++++++++++

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

;+++++++++++++++++++++++++++++++++Delay
;++++++++++++++++++++++++++++++++++++++

delay:
   MOV R0, #10H
  L2: MOV R1,#0FH
  L1: DJNZ R1, L1
   DJNZ R0, L2
   RET

;+++++++++++++++++++++++++++++++++++++++

end


 
Circuit diagram of LCD interfacing with 8051 in 4 bit mode

Circuit diagram of LCD and 8051 interfacing in 4 bit mode


 ALERT: here i use 2 different port of 8051 P1 to connect LCD and P2 to signals. if you try this code with using all in single port may be it not work because then EN switch differently and make wrong command read.
Download keil project file, code and proteus simulation files
 If you enjoy the post please share it. like and follow use on Facebook and Google. thanX

Comments

  1. best explanation about 4bit lcd interfacing on the internet
    Thanks

    ReplyDelete
  2. can one use this code directly in multisim?

    ReplyDelete
  3. @parasbhanot - glad to know you consider it best explanation... and your most welcome, if you want to write some tutorial (open to very one).

    @mase - As you can see i tested it in proteus. but it will also work in multisim. You can simulate in two different ways.
    1. use mutisim simulator and multisim assembler.
    2. assemble code with keil assembler and run in multisim simulator (I attach keil project, link HEX file generated by keil to multisim MCU).

    I hop it work in both ways for you.

    ReplyDelete
  4. I'm getting garbage data on the display. its showing DToEUE2..... please help. I made the connections as shown. thankyou

    ReplyDelete
  5. hey buddy i dont know ur name i dont know who u are ,but ur great bro..bless u buddy..
    but ur code helped me alot to understand the complete code very very clearly.

    ReplyDelete

Post a Comment

Popular posts from this blog

Tutorial for Scroll text on 16x2 LCD with 8051 Microcontroller in c

In our last tutorial we interface 2x16 LCD with 8051 in assembly, now lets display some scrolling text on LCD. it is very useful because generally we have a long text to display and a 2x16 LCD display only 16 character at a time.

Multiplex 4 Seven Segment Display With 8051 In Assembly

Multiplexing is very essential part while working with 8051 because of its limited number of ports. which offer 32 pins for connecting external devices. 32 seems large but when you working with seven segment, keypad, LCD, ADC etc. or if you project have many parts to operate simultaneously then you definitely need to multiplex some of ports.