;=================================================================================== ; FOUR BIT INTERFACING LCD DRIVER FOR 8051 or DERIVATED ; >>> ;----------------------------------------------------------------------------------- ; This utility is used for cotrolled LCD-Display with 4BIT interfacing ; The Port I/O is bit port of microcontroller. The configurations is : ; PORT: Bit 7 6 5 4 3 2 1 0 ; FOR : U U U U D7 D6 D5 D4 ; ; Note: ; - U is used for RS_LCD, RW_LCD and E_LCD pin or another bit output port. ; - 4 bit lcd data bus (for 4 bit interfacing is D7..D4) must be connected to ; bit 0..3 of I/O port (bidirectional, because this interfacing can write/read) ; ; RS_LCD, RW_LCD, E_LCD can connected to Bit 4 to 7. ; Please use pseudo opcode BIT to refer the bit that you like ; The PORT_LCD label is the LCD bit Port address of microcontroller ; ; This driver can intefaced to C language Keil-C51 uVision2 with "extern" prototype ; or Assembly. ;------------------------------------------+---------------------------------------- ; EXTERN PROTOTYPE | FUNCTION ;------------------------------------------+---------------------------------------- ; void init_lcd(void); | Initialaze LCD,LCD ON,NOBLINK,NOCURSOR ; void clr_lcd(void); | Clear LCD and Home Cursor ; void locate_lcd(char row, char col); | Locate cursor (begin 0) ; void csrhome_lcd(void); | Locate cursor to (0,0), char no clear ; void on_lcd(void) | Lcd ON no blink, no cursor ; void off_lcd(void); | Lcd off, character no display, no clear ; void wrchar_lcd(char character); | Display character to current cursor ; void wrstr_lcd(char *buff_char); | Display string depend generic pointer ; | *buff_char, in idata, data, xdata, ; | cdata, and pdata. Automatic pointer. ; void csrmode_lcd(char cur, char blink); | Set cursor mode ;=================================================================================== ; THIS PROGRAM IS TESTED WITH C51 Keil uVision2 Version 6.20 ; THE RESULT WORK FINE, NO ANY TROUBLE ; THE ALL ROUTINE USED REGISTER BANK 0 FOR PARAMETERS PASSING, IF ANOTHER BANK USED ; WILL NOT WORK FINE. ;=================================================================================== NAME Utility_LCD_4Bit_Port Utility_LCD_4Bit_Port_SEG SEGMENT CODE ;========================================================================== ; The following is Control pin configurations. ; If the pin are changed, please the pin configurations are changed by you ;-------------------------------------------------------------------------- RS_LCD BIT P2.4 RW_LCD BIT P2.5 E_LCD BIT P2.6 sfr PORT_LCD = P2; ;========================================================================== PUBLIC init_lcd PUBLIC _wrstr_lcd PUBLIC clr_lcd PUBLIC csrhome_lcd PUBLIC _locate_lcd PUBLIC on_lcd PUBLIC off_lcd PUBLIC _wrchar_lcd PUBLIC _wrctl_lcd PUBLIC _csrmode_lcd RSEG Utility_LCD_4Bit_Port_SEG USING 0 ;========================================================================== ; WRCTL_LCD_4BYTE : write 4bit data for control lcd ;-------------------------------------------------------------------------- ; INPUT : R7 = data 4 bit : 0000DDDD ; OUTPUT : NONE ; REG USES : A, R7 ; NO-PUBLIC to C51 ;========================================================================== wrctl_lcd_4byte: CLR C ; write operation prepare CLR RS_LCD ; select control address SJMP enable_lcd ;========================================================================== ; ENABLE_LCD : write/read 4bit data to/from lcd (data or control) ; and enable operation ;-------------------------------------------------------------------------- ; INPUT : R7 = 4 bit data: 0000DDDD ; CY = 0:write, 1:read operation select ; OUTPUT : R7:data result if read operation is selected ; REG USED : A,R7 ; NO-PUBLIC to C51 ;========================================================================== enable_lcd: MOV RW_LCD,C ; set r/w lcd MOV A,PORT_LCD ; read old data port ORL A,#0FH ; prepare D0..D3=1111 for read ; and prepare D4..D7 not changed JC enable_lcd1 ; jump if read operation ANL A,#0F0H ; masking bit, D4..D7 not change ; D0..D3 = 0000 ORL A,R7 ; ORing for 4 bit data MOV PORT_LCD,A ; output to 4bit data lcd port SJMP enable_lcd2 enable_lcd1: MOV PORT_LCD,A ; write data lcd enable_lcd2: SETB E_LCD ; pulse for E lcd, now high logic NOP ; for timing high logic NOP ; total nop depend to crystal NOP NOP NOP NOP NOP NOP MOV A,PORT_LCD ; no proble this operation for data lcd reading NOP NOP NOP NOP CLR E_LCD ; e_lcd to low logic JNC enable_lcd3 ; if write operation no 4bit data masking ANL A,#0FH ; 4bit data masking MOV R7,A ; return value for C51 language enable_lcd3: RET ;========================================================================== ; BUSY_LCD : read busy lcd flag bit 7 from control lcd ;-------------------------------------------------------------------------- ; INPUT : none ; OUTPUT : CY for busy lcd flag ; REG USED : A,B,R7 ; NO-PUBLIC to C51 ;========================================================================== busy_lcd: SETB C ; read prepare CLR RS_LCD ; select control address CALL enable_lcd ; generated enable pulse MOV B,R7 ; save 4bit return value D4..D7 CALL enable_lcd ; generated enable pulse MOV A,B ; get value D4..D7 JB ACC.3,busy_lcd ; check busy lcd bit 7 RET ; for 4 bit interfacing is bit 3 ;========================================================================== ; _RDCHAR_LCD : read char lcd from current cursor ;-------------------------------------------------------------------------- ; INPUT : none ; OUTPUT : R7 = data ASCII char from current cursor lcd ; REG USED : A,B,R6,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern char rdchar_lcd(void) ;========================================================================== _rdchar_lcd: SETB C ; read prepare SETB RS_LCD ; select data address CALL enable_lcd ; generated enable pulse SWAP A ; shift left 4 position to MSNyble MOV B,A ; save CALL enable_lcd ; generated enable pulse ORL A,B ; joint to LSNyble data MOV R6,A ; save 8bit data CALL busy_lcd ; check busy lcd for high speed access ; because without delay routine MOV R7,AR6 ; return value to C51 language RET ;========================================================================== ; _WRCTL_LCD : write control lcd to perform clear_lcd, locate_lcd etc ;-------------------------------------------------------------------------- ; INPUT : R7 = 8bit data to be writing to lcd as data control ; OUTPUT : none ; REG USED : A,B,R6,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void wrctl_lcd(char) ;========================================================================== _wrctl_lcd: CLR C CLR RS_LCD SJMP _wrchar_lcd1 ;========================================================================== ; _WRCHAR_LCD : write ascii char lcd to perform char display in current cur ;-------------------------------------------------------------------------- ; INPUT : R7 = 8bit data to be writing to lcd as data ascii char ; OUTPUT : none ; REG USED : A,B,R6,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void wrchar_lcd(char) ;========================================================================== _wrchar_lcd: CLR C SETB RS_LCD _wrchar_lcd1: MOV R6,AR7 MOV A,R7 SWAP A ANL A,#0FH MOV R7,A CALL enable_lcd MOV A,R6 ANL A,#0FH MOV R7,A CALL enable_lcd CALL busy_lcd RET ;========================================================================== ; FOR USED FIRT POWER UP TO INITIALIZE LCD ; BECAUSE FOR THE FIRT POWER UP TIME, THE BUSY LCD FLAG CAN NOT READ ; IF YOU HAVE ANOTHER DELAY ROUTINE OUTSIDE THIS DRIVER, ; PLEASE WRITE: PUBLIC to the top line ;========================================================================== delay_lcd: MOV R7,#0FFH delay_lcd1: MOV R6,#0FFH delay_lcd2: DEC R6 MOV A,R6 ORL A,#0 JNZ delay_lcd2 DJNZ R7,delay_lcd1 RET ;========================================================================== ;========================================================================== ; _WRSTR_LCD : write sequence ascci in memory until NULL char is reached ; The memory is free on all 8051 memory mapping as: ; idata, data, xdata, cdata and pdata ; ; This routine check Reg R3 to specify memory type. ; If 00H:idata/data 01H:xdata FFH:cdata FEH:pdata ; ; Automatic generic pointer configuration for C51 language interfacing ;-------------------------------------------------------------------------- ; INPUT : R3 = memory type, R2 = MSB address, R1 = LSB address ; OUTPUT : none ; REG USED : A,B,R6,R7, R0 for pdata/idata/data, DPTR for cdata and xdata ; ; PUBLIC to C51 ; C51 PROTYPE: extern void wrstr_lcd(char*) ;========================================================================== _wrstr_lcd: CJNE R3,#0,_wrstr_lcd_xdata ; for idata memory MOV R0,AR1 _wrstr_lcd_idata1:MOV A,@R0 ORL A,#0 JZ _wrstr_lcd_exit MOV R7,A CALL _wrchar_lcd INC R0 SJMP _wrstr_lcd_idata1 _wrstr_lcd_xdata: CJNE R3,#1,_wrstr_lcd_cdata ; for xdata memory MOV DPH,R2 MOV DPL,R1 _wrstr_lcd_xdata1:MOVX A,@DPTR ORL A,#0 JZ _wrstr_lcd_exit MOV R7,A CALL _wrchar_lcd INC DPTR SJMP _wrstr_lcd_xdata1 _wrstr_lcd_cdata: CJNE R3,#0FFH,_wrstr_lcd_pdata ; for cdata memory MOV DPH,R2 MOV DPL,R1 _wrstr_lcd_cdata1:CLR A MOVC A,@A+DPTR ORL A,#0 JZ _wrstr_lcd_exit MOV R7,A CALL _wrchar_lcd INC DPTR SJMP _wrstr_lcd_cdata1 _wrstr_lcd_pdata: CJNE R3,#0FEH,_wrstr_lcd_exit ; for external page memory MOV R0,AR1 _wrstr_lcd_pdata1:MOVX A,@R0 ORL A,#0 JZ _wrstr_lcd_exit MOV R7,A CALL _wrchar_lcd INC R0 SJMP _wrstr_lcd_pdata1 _wrstr_lcd_exit: RET ;========================================================================== ; CLR_LCD : clear all character in lcd, move to home cursor ;-------------------------------------------------------------------------- ; INPUT : none ; OUTPUT : none ; REG USED : A,B,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void clr_lcd(void) ;========================================================================== clr_lcd: MOV R7,#1 CALL _wrctl_lcd RET ;========================================================================== ; CSRHOME_LCD : move cursor to home position ;-------------------------------------------------------------------------- ; INPUT : none ; OUTPUT : none ; REG USED : A,B,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void csrhome_lcd(void) ;========================================================================== csrhome_lcd: MOV R7,#2 CALL _wrctl_lcd RET ;========================================================================== ; _LOCATE_LCD : move cursor to row,col ;-------------------------------------------------------------------------- ; INPUT : R7 = row, R5 = col, 0 is the firt col/row ; OUTPUT : none ; REG USED : A,B,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void locate_lcd(char row, char col) ;========================================================================== _locate_lcd: CJNE R7,#0,_locate_lcd1 ; row 0 MOV A,#80H SJMP _locate_lcd4 _locate_lcd1: CJNE R7,#1,_locate_lcd2 ; row 1 MOV A,#0C0H SJMP _locate_lcd4 _locate_lcd2: CJNE R7,#2,_locate_lcd3 ; row 2 MOV A,#94H SJMP _locate_lcd4 _locate_lcd3: CJNE R7,#3,_locate_lcd5 ; row 3 MOV A,#0D4H _locate_lcd4: ADD A,R5 ; add to col MOV R7,A CALL _wrctl_lcd _locate_lcd5: RET ;========================================================================== ; OFF_LCD : off lcd display, all char not clear only no-display ;-------------------------------------------------------------------------- ; INPUT : none ; OUTPUT : none ; REG USED : A,B,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void off_lcd(void) ;========================================================================== off_lcd: MOV R7,#08H SJMP on_lcd1 on_lcd: MOV R7,#0CH on_lcd1: CALL _wrctl_lcd RET ;========================================================================== ; OFF_LCD : setting lcd cursor to blink or/not/and cursor ;-------------------------------------------------------------------------- ; INPUT : R7 = cursor 1:on 0:off ; R5 = blink 1:on 0:off ; OUTPUT : none ; REG USED : A,B,R7 ; ; PUBLIC to C51 ; C51 PROTYPE: extern void csrmode_lcd(char cursor, char blink) ;========================================================================== _csrmode_lcd: MOV B,#0CH MOV A,R7 JZ _csrmode_lcd1 INC B INC B _csrmode_lcd1: MOV A,R5 JZ _csrmode_lcd2 INC B _csrmode_lcd2: MOV R7,B CALL _wrctl_lcd RET ;========================================================================== ; Initialize LCD for the first time on power up ;========================================================================== init_lcd: MOV R7,#03H CALL wrctl_lcd_4byte CALL delay_lcd MOV R7,#03H CALL wrctl_lcd_4byte CALL delay_lcd MOV R7,#03H CALL wrctl_lcd_4byte MOV R7,#02H CALL wrctl_lcd_4byte MOV R7,#028H CALL _wrctl_lcd MOV R7,#0CH CALL _wrctl_lcd MOV R7,#01H CALL _wrctl_lcd MOV R7,#06H CALL _wrctl_lcd CALL delay_lcd RET ;========================================================================== END