Wednesday, April 13, 2016

16x2 LCD Interface with 89C51

This tutorial describes the software and hardware needed to interface 16x2 LCD an Hitachi HD44780 LCD controller to a AT89C51 microcontroller. The HD44780 is one of the most common controllers used for character displays from one up to four lines. It is also available from several different manufacturers. This tutorial demonstrates how to interface and program a four lines of 16 characters display. The hardware is simple.

Figure 1 shows the hardware schematic

16x2 LCD Interface with 89C51

Sample Assembly Code for 4-bit mode 16x2 LCD Interface:
For C code of 4-Bit LCD interface Click Here LCD Interface in 4-Bit Mode requires only 6 IO Lines.
INCLUDE 89C51.MC
;-----------------------LCD 4-bit--------------------------
;LCD Connections to microcontroller
E  EQU P0.4  ; PIN 6 enable
RS   EQU P0.5  ; /register select

DATA  EQU P0  ; data lines P0-P3
;----------------------------------------------------------
(0000H):
 JMP on_reset
;----------------------------------------------------------
(00FFH):
on_reset: 
  MOV DPTR,#init_data
  CALL disp_init
  
  MOV DPTR,#message1
  CALL disp_string
  
  CALL disp_line2
  
  MOV DPTR,#message2
  CALL disp_string

ENDLESS:
  JMP ENDLESS 
;----------------------------------------------------------
; display char in A
; used reg R2
disp_char:
  SETB RS   ; desable register select
  
  MOV R2,A
  ANL A,#F0H   ; send high nybble first
  RR A
  RR A
  RR A
  RR A
  ANL DATA,#F0H
  ORL DATA,A
  
  SETB E   ; give E pulse
  CALL delay_data
  CLR E
  CALL delay_data
  
  MOV A,R2
  ANL A,#0FH   ; send lower nybble
  ANL DATA,#F0H
  ORL DATA,A
  
  SETB E   ; give E pulse
  CALL delay_data
  CLR E
  CALL delay_data
  
  
RET
;----------------------------------------------------------
; used registers A,R1,R7
disp_string:
  MOV A,#00H
  MOV R1,#00h
next_char:
  INC R1   
  MOVC A,@A+DPTR
   MOV DATA,A
   CALL disp_char
   MOV A,R0
  CJNE R1,#0Fh,next_char   
RET
;----------------------------------------------------------
; used registers A,R1,R7,R2
disp_init:
  CLR RS   ; enable /register select
  MOV A,#00H
  MOV R1,#00h
next_chari:
  INC R1   
  MOVC A,@A+DPTR
  MOV R2,A   ; take backup
  
  ANL A,#F0H   ; send high nybble first
  RR A
  RR A
  RR A
  RR A
  ANL DATA,#F0H
  ORL DATA,A
  
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init
  
  MOV A,R2
  ANL A,#0FH   ; send lower nybble
  ANL DATA,#F0H
  ORL DATA,A
  
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init

  MOV A,R0
  CJNE R1,#02h,next_chari 
  

RET
;----------------------------------------------------------
disp_line1:
  CLR RS   ; register select
  ANL DATA,#F0H
  ORL DATA,#08H  ; first line address
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init
  
  ANL DATA,#F0H  ; second nybble
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init

RET
;----------------------------------------------------------
disp_line2:
  CLR RS   ; register select 
  ANL DATA,#F0H  ; next line address
  ORL DATA,#0AH
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init
  
  ANL DATA,#F0H  ; next line address
  ORL DATA,#08H
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init

RET
;----------------------------------------------------------
;2 msec delay
delay_data:
  MOV R7,#FFH
del:  NOP
  NOP
  DJNZ R7, del 
RET
;----------------------------------------------------------
;20 msec delay
delay_init:
  MOV R7,#FFH
del1:  NOP
  NOP
  NOP
  NOP
  NOP
  NOP
  NOP
  DJNZ R7, del1 

RET
;----------------------------------------------------------
message1:
DB "Testing 123.... "
message2:
DB "It's working    "
init_data:
DB 0FH ; Display On, Cursor On,Cursor Blink On(1)/Off(0)
DB 01H ; Clear Display
DB 38H ; Set Interface Length

Sample Assembly Code for 8-bit mode 16x2 LCD Interface:
For C code Click here

8-Bit mode is simple to interface but it takes 10-IO lines. I will recommend go for 4-bit mode interface


INCLUDE 89C51.MC
;-----------------------LCD 8-bit--------------------------
;LCD Connections to microcontroller
E  EQU P2.0  ; PIN 6 enable
RS   EQU P2.1  ; /register select

DATA  EQU P0  ; data lines
;----------------------------------------------------------
(0000H):
 JMP on_reset
;----------------------------------------------------------
(00FFH):
on_reset: 
  MOV DPTR,#init_data
  CALL disp_init
  
  MOV DPTR,#message1
  CALL disp_string
  
  CALL disp_line2
  
  MOV DPTR,#message2
  CALL disp_string

ENDLESS:
  JMP ENDLESS 
;----------------------------------------------------------
; display char in A
disp_char:
  SETB RS   ; desable register select
  MOV DATA,A
  SETB E   ; give E pulse
  CALL delay_data
  CLR E
  CALL delay_data
RET
;----------------------------------------------------------
; used registers A,R1,R7
disp_string:
  MOV A,#00H
  MOV R1,#00h
next_char:
  INC R1   
  MOVC A,@A+DPTR
   MOV DATA,A
   CALL disp_char
   MOV A,R0
  CJNE R1,#0Fh,next_char   
RET
;----------------------------------------------------------
; used registers A,R1,R7
disp_init:
  CLR RS   ; enable /register select
  MOV A,#00H
  MOV R1,#00h
next_chari:
  INC R1   
  MOVC A,@A+DPTR
   MOV DATA,A
   SETB E  ; give E pulse
   CALL delay_init
   CLR E
   CALL delay_init
   MOV A,R0
  CJNE R1,#02h,next_chari 
  

RET
;----------------------------------------------------------
disp_line1:
  CLR RS   ; register select
  MOV DATA,#80H  ; first line address
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init
RET
;----------------------------------------------------------
disp_line2:
  CLR RS   ; register select 
  MOV DATA,#A8H  ; next line address
  SETB E   ; give E pulse
  CALL delay_init
  CLR E
  CALL delay_init
RET
;----------------------------------------------------------
;2 msec delay
delay_data:
  MOV R7,#FFH
del:  NOP
  NOP
  DJNZ R7, del 
RET
;----------------------------------------------------------
;20 msec delay
delay_init:
  MOV R7,#FFH
del1:  NOP
  NOP
  NOP
  NOP
  NOP
  NOP
  NOP
  DJNZ R7, del1 

RET
;----------------------------------------------------------
message1:
DB "Testing 123.... "
message2:
DB "It's working    "
init_data:
DB 0FH ; Display On, Cursor On,Cursor Blink On(1)/Off(0)
DB 01H ; Clear Display
DB 38H ; Set Interface Length


For C code of 4-Bit LCD interface Click Here

Microcontroller interface
The HD44780 controller can be set up to communicate with 4–bit or 8–bit microcontrollers. The fastest way to communicate is to set up the interface for 8–bit communication and then interface the display as a memory mapped device. The drawbacks of this solution are located in the “glue” logic needed to interface the display and in the fact that wait states need to be programmed to avoid timing violations when interfaced to a 89C51.

This application note shows how to interface the controller using the 4–bit interface mode. When the controller is set up for 4–bit communication, the following signals are used:

  •  DB4, DB5, DB6, DB7 Multiplexed data bus signals (four bits are sent twice to form a byte)  
  •  RS Register select
  • R/W Read / Write signal
  • E Enable

Contrast control
The recommended way to adjust the LCD contrast is to connect the Vo input of the display to a 10 kΩ variable resistor as shown in Figure 2. Adjustment in then done during factory setup. 


Timing
Execution times: Clear display 1.64 ms; Home cursor 40 μs; all others 40μs, except read busy flag which is complete in a single enable cycle (or two cycles in 4–bit mode), and character generator ram reads and writes which should be separated by 120μs delays. These execution times mean that after an operation, the CPU must perform Busy Flag checks until the BF (bit 7) is 0, or, when the connection to the module from the CPU is write–only, wait more than the execution time before the next operation. These times are usually strict, LCDs used in a write–only configuration should provide the specified delays.




No comments:

Post a Comment