tee_say
Newbie level 4
Hey Friend can help check this assembly code? I cant display word at Line 2 on my 16x2 LCD. My LCD model is C216, Crystal Clear Technology :: The Total Display Solution Provider... TQ. I using p16f876a and 4 bit LCD interface with pic.
list P=P16F876A
INCLUDE "P16F876A.INC"
; ERRORLEVEL -302
__CONFIG _PWRTE_ON & _HS_OSC & _WDT_OFF & _LVP_OFF & _BODEN_OFF; configuration switches
;*******************************************
; 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
movlw 0x00
movwf PCLATH
goto START
;initialise
INITPIC
bsf STATUS,RP1 ;sellect bank 1
movlw b'00000000'
movwf PORTB ;set as output
bcf STATUS,RP1 ;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 0x32 ;wait for about 5ms
CALL DLY1
MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E=HIGH
MOVWF PORTB
BCF PORTB,BIT_E
MOVLW 0x01 ;
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'11101000' ;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 PORTB ;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 PORTB
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'10001000'
MOVWF PORTB
BCF PORTB,BIT_E
MOVLW B'10001000'
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'115' ;s
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
list P=P16F876A
INCLUDE "P16F876A.INC"
; ERRORLEVEL -302
__CONFIG _PWRTE_ON & _HS_OSC & _WDT_OFF & _LVP_OFF & _BODEN_OFF; configuration switches
;*******************************************
; 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
movlw 0x00
movwf PCLATH
goto START
;initialise
INITPIC
bsf STATUS,RP1 ;sellect bank 1
movlw b'00000000'
movwf PORTB ;set as output
bcf STATUS,RP1 ;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 0x32 ;wait for about 5ms
CALL DLY1
MOVLW B'00111000' ;FUNCTION SET - 8 BIT, BIT_E=HIGH
MOVWF PORTB
BCF PORTB,BIT_E
MOVLW 0x01 ;
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'11101000' ;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 PORTB ;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 PORTB
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'10001000'
MOVWF PORTB
BCF PORTB,BIT_E
MOVLW B'10001000'
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'115' ;s
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