3-Wire LCD Interface For 8051 Systems Submitted by: Vidyasagaran P. (v_sagar_p@yahoo.

com) ; ------------- READS51 generated header -------------; module : C:\Rigel\Reads51\Work\LCD\LCD.asm ; created : 20:34:08, Thursday, August 15, 2002 ; author : Vidyasagaran P. (v_sagar_p@yahoo.com) ; This file contains all the routines needed to manipulate the LCD display ; Please note that these routines are hardware wiring specific and will need ; changes if the wiring changes. You may have to adjust the delay (DLY_IDX) depe nding on ; the processor speed. ; +-------+ +---------------+ ; P0.0+-------------------------------------->+E LCD ; +----------+ ; P0.1+-------------->+CLK D5+----------->+RS R/W+---+ ; P0.2+-------------->+INPUT D0-4+--------\-->+D4-D7 ; +--\-->+D0-D3 - Gn d ; +-------+ +----------+ +---------------+ ; 8051 74HC164 -Gnd LCD display ; How data is loaded into the LCD ; ; 1. clock the upper nibble in and use E bit to latch the higher 4 bits ; 2. clock the lower nibble in similarly ; ----------------------------------------------------; ; The following definitions are as per the ABOVE hardware wiring. ; It assumes 3 port pins used for display functions. First one directly connecte d to LCD ; E (enable) bit and reset two are connected to an 8 bit output shift register a s below. #include <sfr51.inc> ;----------------------- PORTING Changes to be done in the following --------#define LCD_PORT P3 ;Port used for LCD interface #define BASE 000 ;where the code this located #define DLY_IDX 2FH ;depends on speed of processor #define EBIT LCD_PORT.0 #define S2P_CLK LCD_PORT.1 #define S2P_IN LCD_PORT.2 CodeSeg segment code Public _Init_LCD Public _display_string rseg Codeseg org BASE _Init_LCD: clr ared. EBIT ;reset the LCD E bit used. Other pins need not be cle ;LCD Ebit pin ;Serial to parallel convertor 74HC164 clock pin ;Serial to parallel convertor 74HC164 serial input

acall mov acall ret

init_lcd DPTR,#Init_msg _display_string

;----------------------------------------------------------;clear_home_cursor - put the cursor back to first char clear_home_cursor: ;clear display clr c mov acc,#00000001b acall _write_char ;home cursor clr c mov acc,#00000010b acall _write_char ret ;----------------------------------------------------------;_display_string is a function which assumes the address of the string ;to be passed in DPTR, in the code memory. Strin must have a NULL at the end. _display_string: mov acc,r1 ;save R1 push acc mov acc,r0 ;save R0, as this is destroyed in _write_char push acc acall clear_home_cursor mov r1,#0 ;index count for next character display_string_loop: mov a,r1 ;move index count to accumulator movc a,@a+DPTR ;next char to go jz display_string_out ;is it a null? setb c ;if not null set carry to write char acall _write_char ;call write_char function inc r1 ;next char to go sjmp display_string_loop ;repeat till all chars are done display_string_out: pop mov pop mov ret acc r0,acc acc r1,acc ;restore R0 as write_char destroys this ;restore R1

;----------------------------------------------------------;A character is passed in to this routine in accumulator ;this routine assumes the following wiring from uP to the LCD. ;R0 is destroyed. But exported functions "display_string" saves this, ;(a precausion which is optimised also!) _write_char: mov ov,c ;store state of c for second nibble write mov r0,#5 ;we need to shift these many times setb ac ;this indicates second nibble needs to be writte n yet write_char_loop: mov S2P_IN,c clr S2P_CLK ;serial input bit ;clock once

setb rlc djnz

S2P_CLK a ;get c flag set as per data bits from next time r0,write_char_loop

;make the LCD latch the value setb EBIT ;pulse Ebit for one time for the first nibble clr EBIT jnb clr rrc mov le mov sjmp r0,#5 ;we need to write these many times write_char_loop ;for command writes delay is needed, not ac,write_char_over ac ;get out after the second nibble written a c,ov ;remove that extra rotation ;restore the original carry to write second nibb

write_char_over: jb ov,write_char_nodelay for chars! acall big_dly write_char_nodelay: ret

;---------------------------------------------------------;write_one_nibble : writes one Most significant nibble in a passed char ;to the LCD. Caller should set the C to indicate write to LCD command ;Assumes left roation of bits and hence wiring of data bits from Latch ;to be accordingly ;contents of R0 is destroyed write_one_nibble: mov r0,#5 ;we need to write these many times write_one_nibble_loop: mov S2P_IN,c ;serial input bit clr S2P_CLK ;clock once setb S2P_CLK rlc a ;get c flag set as per data bits from second tim e djnz r0,write_one_nibble_loop ;make the LCD latch the value setb EBIT ;pulse Ebit for one time for the first nibble clr EBIT acall big_dly ret ;---------------------------------------------------------;a big delay for the LCD to settle after each init stuff. Some places this ;delay seems to be very critical. I have put more since it doesn't take much ;time and also since it is only one time init. big_dly: mov r0,#DLY_IDX odly: mov acc,#FFH dly: djnz acc,dly ;Simulater virtually hangs here. So comment this during simulation djnz r0,odly ret

;---------------------------------------------------------;init_lcd : the following routine works fine from the first write after ;the power is applied. "write_one_nibble" is used to change the LCD mode ;from 8 bit interface to 4 bit one. For this write alone the D0-D3 is taken ;as 0000 as they are hardwired to ground. init_lcd: ;set display width clr c mov acc,#00100000b acall write_one_nibble ;enable clr mov acall ;clear clr mov acall display and cursor c acc,#00001100b _write_char display c acc,#00000001b _write_char

;no cursor and no blink

;home cursor clr c mov acc,#00000010b acall _write_char ret ;----------------------------------------------------------Init_msg: DB "Display OK",0 end Back to the 8051 projects section HERE

Sign up to vote on this title
UsefulNot useful