list p=PIC16F84A include ;******************************************* ; 4 BIT LCD interface with PIC ; only port B is implemented ; RB7-RB4 = DB7-DB4 ; RB3=E ; RB2=RW ; RB1=RS ;******************************************* ;decleration BIT_E EQU 3 BIT_RW EQU 2 BIT_RS EQU 1 TEMP EQU 0x020 ;TEMP STORAGE V_DLY EQU 0x021 ; Variable for DLY V_DLY1 EQU 0x022 ; for DLY1 org 0h ;start of program at goto START ;initialise INITPIC bsf STATUS,RP0 ;sellect bank 1 movlw b'00000000' movwf TRISB ;set as output bcf STATUS,RP0 ;select bank 0 clrf PORTB return INITLCD ;INITIALIZE LCD MOVLW 0xFE ;WAIT LONG CALL DLY1 ;254 * 0.5 = DELAY OF 127ms ;BUSY FLAG CAN'T BE CHECKED RIGHT NOW MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E = HIGH MOVWF PORTB BCF PORTB,BIT_E ; BIT_E = LOW MOVLW 0x0A ;wait for about 5ms CALL DLY1 MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E=HIGH MOVWF PORTB BCF PORTB,BIT_E MOVLW 0x02 ; CALL DLY1 MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E = high MOVWF PORTB BCF PORTB,BIT_E ;BIT_E=LOW ;above i have done same command 3 times, this may be not necessary, i just followed datasheet CALL LCDBUSY ;BUSY FLAG CAN BE CHECKED NOW! MOVLW B'00101000' ;FUNCTION SET - 4 BIT ,BIT_E = HIGH MOVWF PORTB BCF PORTB,BIT_E ;..........EVERY INSTRUCTION WILL BE OF 2 CYCLE FROM HERE CALL LCDBUSY ;..FUNCTION SET.. MOVLW B'00101000' MOVWF PORTB BCF PORTB,BIT_E ;1 CYCLE COMPLETE MOVLW B'10001000' MOVWF PORTB BCF PORTB,BIT_E ;2 CYCLE CALL LCDBUSY ;DISPLAY CONTROL - MOVLW B'00001000' ; 1ST NIBBLE AND BIT_E=1,BIT_RW=0,BIT_RS=0 MOVWF PORTB BCF PORTB,BIT_E ;1 CYCLY MOVLW B'11111000' ;DISPLAY CONTROL NIBBLE (DISP=ON,CURSOR=ON,BLINK=ON) AND BIT_E=1,BIT_RW=0,BIT_RS=0 MOVWF PORTB BCF PORTB,BIT_E ;2 CYCLE CALL LCDBUSY ;CLEAR DISPLAY AND HOME CURSOR MOVLW B'00001000' MOVWF PORTB BCF PORTB,BIT_E MOVLW B'00011000' MOVWF PORTB BCF PORTB,BIT_E CALL LCDBUSY ;ENTRY SET - MOVLW B'00001000' ; BIT_E=1,BIT_RW=0,BIT_RS=0 MOVWF PORTB BCF PORTB,BIT_E ;1 CYCLE MOVLW B'01101000' ;ENTRY SET - INCREMENT,NO DISP SHIFT(CUR SHIFT),BIT_E=1,BIT_RW=0,BIT_RS=0 MOVWF PORTB BCF PORTB,BIT_E ;2 CYCLE RETURN LCDBUSY BSF STATUS,RP0 ;SELLECT BANK 1 MOVLW B'11110000' MOVWF TRISB ;SET RB7-RB4 INPUT BCF STATUS,RP0 ;SELLECT BANK 0 BSF PORTB,BIT_RW BCF PORTB,BIT_RS BSF PORTB,BIT_E MOVF PORTB,W ;READ BCF PORTB,BIT_E ;1 CYCLE complete BSF PORTB,BIT_RW BCF PORTB,BIT_RS BSF PORTB,BIT_E NOP ;DO NOTTHING COZ BUSY FLAG IS IN FIRST NIBBLE BCF PORTB,BIT_E ;2nd CYCLE complete ANDLW 0x80 BTFSS STATUS,Z ;CHECK BUSY GOTO LCDBUSY ;LOOP IF BUSY BCF PORTB,BIT_RW ;** BSF STATUS,RP0 ;NOT BUSY SO MAKE PORT B O/P MOVLW 0x000 MOVWF TRISB BCF STATUS,RP0 RETURN ;LCD COMMANDS--- i have written routines for only 2 basic commands, ; one has to write routines for shifting display/crussor, home crussor etc. ;it's easy just follow datasheet and i'll include it someday! LINE2 ;by selecting DDRAM address = 0x40 in case of 16x4 line LCD, see datasheet of HD44780 MOVLW B'11001000' MOVWF PORTB BCF PORTB,BIT_E MOVLW B'00001000' MOVWF PORTB BCF PORTB,BIT_E RETURN LCDWRITE ;Writes data/character in W register to sellected CG/DD RAM, see its use in START routine MOVWF TEMP CALL LCDBUSY MOVF TEMP,W ANDLW B'11110000' IORLW B'00001010' ;BIT_E=1,BIT_RW=0,BIT_RS=1 MOVWF PORTB BCF PORTB,BIT_E ;1 CYCLE COMPLETE SWAPF TEMP,W ;SWAP NIBBLES AND STORE IN W REGISTER ANDLW B'11110000' IORLW B'00001010' ;BIT_E=1,BIT_RW=0,BIT_RS=1 MOVWF PORTB BCF PORTB,BIT_E ;2 CYCLE COMPLETE RETURN ;Delay routines ;500uS delay with 4MHz DLY MOVLW D'165' MOVWF V_DLY DLY_LOOP DECFSZ V_DLY, F GOTO DLY_LOOP RETURN ; w times DLY DLY1 MOVWF V_DLY1 DLY1_LOOP CALL DLY DECFSZ V_DLY1, F GOTO DLY1_LOOP RETURN START CALL INITPIC ;initialize PIC CALL INITLCD ;initialize LCD MOVLW D'72' ;H ;Write to DDRAM which is displayed in LCD, DDRAM already sellected at initialization CALL LCDWRITE MOVLW D'69' ;E CALL LCDWRITE MOVLW D'76' ;L CALL LCDWRITE MOVLW D'76' ;L CALL LCDWRITE MOVLW D'79' ;O CALL LCDWRITE MOVLW D'32' ; 0x20 space CALL LCDWRITE MOVLW D'87' ;W CALL LCDWRITE MOVLW D'79' ;O CALL LCDWRITE MOVLW D'82' ;R CALL LCDWRITE MOVLW D'76' ;L CALL LCDWRITE MOVLW D'68' ;D CALL LCDWRITE MOVLW D'33' ;! CALL LCDWRITE CALL LINE2 ;set crussor to line 2 MOVLW D'76' ;L CALL LCDWRITE MOVLW D'73' ;I CALL LCDWRITE MOVLW D'78' ;N CALL LCDWRITE MOVLW D'69' ;E CALL LCDWRITE MOVLW D'32' ;space CALL LCDWRITE MOVLW D'50' ;2 CALL LCDWRITE LOOP NOP GOTO LOOP ;endless loop END