no entiendo un código para LCD 16x2

buenas...
a falta de un buen tuto que explique cómo controlar un lcd con un pic
estoy descifrando los programas ya hechos que encuentro en ensamblador

el siguiente código funciona (aunque creo que tiene un error en el número de direcciones DDRAM porque no escribe en la segunda linea)

mi consulta es porqué al principio configura el setup en 8 bits y despues en 4???
al final en el hardware termina usando el de 4 pero no entiendo porque pone en principio 8
lee el busy flag

la pagina de donde lo saqué: http://patna.sancharnet.in/guria741/pic2lcd/pic2lcd.htm

Código:
			list	p=PIC16F84A
		include 	<P16F84A.INC>
;*******************************************
;	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   '11111110'
		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     ;00001000 => 00000000

		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	ORTB,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    ; leer
		BCF		PORTB,BIT_RS    , a registro de control
		
		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       ;     0xFE		WAIT LONG   '11111110'
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
 
Atrás
Arriba