Hola t-rave.
Las rutinas que tengo son para el modo de operación de 4 bits (así se ahorran unas cuantas patillas del PIC).
Te pongo el código que... aunque un poco lioso, si lo miras detenidamente es muy fácil. Lo unico que puede parecer un poco extraño son las rutinas de enviar un caracter o un comando. Como el modo de operación es de 4 bits, sólo utilizo los 4 bits de mayor peso del PORTC. Es decir, mientras manipulamos el LCD podemos utilizar los 4 bits de menor peso del PORTC sin ningún problema (por eso estas rutinas las he cambiado un poco).
<span class="texto_mini">Codigo:</span>
;;##########################################################################################
#
;#
;# RUTINAS PARA EL DISPLAY (SSC2A16DLNW-E)
;#
;# Patillas display:
;#
;# Vcc 1
;# GND 2
;# La patilla 5 a GND
;# la patilla 3 a GND (si en lugar de ponerla a GND directamente ponemos 1 diodo
;# cambiaremos la luminosidad de las letras del display. Si
;# se pone un potenciometro... mejor que mejor.
;#
;#
;# PIC DISPLAY
;#
;# RC7 14
;# RC6 13
;# RC5 12
;# RC4 11
;#
;# RE0 4
;# RE1 6
;#
;#
;#
;###########################################################################################
;-------------------------------------------------------------------------------------------
;
; Inicializamos los puertos correspondientes del display LCD (RC7, RC6, RC5, RC4, RE0, RE1)
;
;-------------------------------------------------------------------------------------------
Port_LCD
BSF STATUS,RP0 ;Selecciona el banco 1
movlw b"00001111" ; PUERTO C = 0000 1111 (Los pines IN)
movwf TRISC
bcf TRISE,PSPMODE ; Para que el Puerto E puedan ser I/O digitales.
bcf TRISE,0 ; PUERTO E como salidas
bcf TRISE,1
bcf TRISE,2
BCF STATUS,RP0 ;Selecciona el banco 0
bcf PORTE,1
RETURN
;-------------------------------------------------------------------------------------------
;
; Inicializamos el display LCD
;
;-------------------------------------------------------------------------------------------
Ini_LCD2
bcf PORTE,0
bcf PORTE,1
MOVLW 0x01E
call X_DELAY500
bcf PORTC,7
bcf PORTC,6
bsf PORTC,5
bsf PORTC,4
movf PORTC,W
CALL LCDPUTCMD
MOVLW 0x010 ; 5 ms
call X_DELAY500
bcf PORTC,7
bcf PORTC,6
bsf PORTC,5
bsf PORTC,4
movf PORTC,W
CALL LCDPUTCMD
CALL DELAY500 ; 500 us
bcf PORTC,7
bcf PORTC,6
bsf PORTC,5
bsf PORTC,4
movf PORTC,W
CALL LCDPUTCMD
CALL DELAY500 ; 500 us
MOVLW 0x01E
call X_DELAY500
; 00100000 MODO DE OPERACION DE 4 BITS
bcf PORTC,7 ; X
bcf PORTC,6 ; X
bsf PORTC,5 ; 1 para configurar el juego de instrucciones.
bcf PORTC,4 ; 1 -> 8 bits, 0 -> 4 bits.
movf PORTC,W
CALL LCDPUTCMD
bsf PORTC,7 ; 1 -> 2 lineas, 0 -> 1 linea.
bcf PORTC,6 ; 1 -> 5x10 puntos, 0 -> 5x7 puntos.
bcf PORTC,5 ; X
bcf PORTC,4 ; X
movf PORTC,W
CALL LCDPUTCMD
CALL DELAY500
; 00001000 DISPLAY OFF, CURSOR OFF, ...
bcf PORTC,7 ; X
bcf PORTC,6 ; X
bcf PORTC,5 ; X
bcf PORTC,4 ; X
movf PORTC,W
CALL LCDPUTCMD
bsf PORTC,7 ; Display encendido/apagado
bcf PORTC,6 ; 1 -> encendido, 0 -> apagado.
bcf PORTC,5 ; 1 -> si cursor, 0 -> no cursor.
bcf PORTC,4 ; 1 -> si parpadea, 0 -> no parpadea.
movf PORTC,W
CALL LCDPUTCMD
MOVLW 0x04
CALL DELAY500
; 00000001 CLEAR LCD
bcf PORTC,7 ; X
bcf PORTC,6 ; X
bcf PORTC,5 ; X
bcf PORTC,4 ; X
movf PORTC,W
CALL LCDPUTCMD
bcf PORTC,7 ; X
bcf PORTC,6 ; X
bcf PORTC,5 ; X
bsf PORTC,4 ; Hacemos un LCD CLEAR
movf PORTC,W
CALL LCDPUTCMD
MOVLW 0x04
CALL X_DELAY500
; 00001100 LCD ON
bcf PORTC,7 ; X
bcf PORTC,6 ; X
bcf PORTC,5 ; X
bcf PORTC,4 ; X
movf PORTC,W
CALL LCDPUTCMD
bsf PORTC,7 ; Display encendido/apagado
bsf PORTC,6 ; 1 -> encendido, 0 -> apagado.
bcf PORTC,5 ; 1 -> si cursor, 0 -> no cursor.
bcf PORTC,4 ; 1 -> si parpadea, 0 -> no parpadea.
movf PORTC,W
CALL LCDPUTCMD
CALL DELAY500
; 00000110 AUTO-INCREMENTO DEL CURSOR
bcf PORTC,7 ; X
bcf PORTC,6 ; X
bcf PORTC,5 ; X
bcf PORTC,4 ; X
movf PORTC,W
CALL LCDPUTCMD
bcf PORTC,7 ; X
bsf PORTC,6 ; Entry Mode Set
bsf PORTC,5 ; 1 -> incrementamos el cursor cuando escribimos, 0 -> decrementamos el cursor cuando escribimos.
bcf PORTC,4 ; 1 -> creo que hace un despalazamiento de todo el display.
movf PORTC,W
CALL LCDPUTCMD
RETURN
;-------------------------------------------------------------------------------------------
;
; Para enviar un comando al display LCD (mirar la funcion LCDPUTCHAR y observar la explicación)
;
;-------------------------------------------------------------------------------------------
LCDPUTCMD
movwf COMANDO_LCD
movlw b"00001111" ; borramos la parte alta del puerto C.
andwf PORTC,F
bcf PORTE,0 ; RS
bsf PORTE,1 ; E
movf COMANDO_LCD,W
iorwf PORTC,F
bcf PORTE,1 ; E
return
;-------------------------------------------------------------------------------------------
;
; Para enviar un caracter al display LCD
;
; Manipulamos los 4 bits de mayor peso del PORTC dejando los otros intactos
;
; 1010 AAAA -> Dato en el PORTC
;
; Si hacemos un AND
;
; 1010 AAAA
; 0000 1111 (AND)
; ---------------
; 0000 AAAA
;
; 10010110 -> Caracter a enviar al display LCD (está en LCDcaracter)
;
; Primero enviaremos los 4 bist de menor peso y despues los otros cuatro
;
; 1001 0110
; 1111 0000 (AND)
; ---------------
; 1001 0000
;
; despues hacemos
;
; 1001 0000
; 0000 AAAA (OR)
; --------------
; 1001 AAAA -> ESTE ES EL DATO QUE ENVIAMOS AL PORTC (observar que solo cambiamos los 4 bits de mayor peso)
;
; YA HEMOS ENVIADO LA MITAD DEL CARACTER, AHORA ENVIAMOS LA OTRA MITAD (esto es asi porque el display lo tenemos configurado en 4 bits)
;
; 10010110 -> Caracter a enviar al display LCD (está en LCDcaracter)
;
; 1001 0110
; 0000 1111 (AND)
; ---------------
; 0000 0110 -> Estos son los 4 bits de menor peso.
;
; ahora lo rotamos a la izquierda 4 veces y obtenemos:
;
; 0110 0000 = LCDcaracter
;
; ahora hacemos PORTC AND 00001111
;
; 1001 AAAA -> El puerto C se habia quedado así de las anteriores operaciones
; 0000 1111 (AND)
; ---------------
; 0000 AAAA
;
; Y ahora metemos la parte que nos quedaba de LCDcaracter
;
; 0000 AAAA
; 0110 0000 (OR)
; --------------
; 0110 AAAA -> ESTE ES EL DATO QUE ENVIAMOS AL PORTC (observar que solo cambiamos los 4 bits de mayor peso)
;
;-------------------------------------------------------------------------------------------
LCDPUTCHAR
MOVWF LCDcaracter ; Character to be sent is in W
movf PORTC,W
andlw b"00001111" ; borramos la parte alta del puerto C. (los bits de menor peso del PORTC no los queremos tocar)
movwf AUXILIAR
BSF PORTE,0 ; Set LCD in data mode
BSF PORTE,1 ; LCD E-line High
movf LCDcaracter,W
andlw b"11110000" ; NOS QUEDAMOS CON LA PARTE ALTA DEL BYTE, la parte baja la hacemos "cero"
iorwf AUXILIAR,F ; En AUXILIAR se encuentran los 4 primeros bits del codigo ascii que mandamos al display
movf AUXILIAR,W
movwf PORTC
BCF PORTE,1 ; LCD E-line Low
nop
BSF PORTE,1 ; LCD E-line High
movf LCDcaracter,W
andlw b"00001111" ; NOS QUEDAMOS CON LA PARTE BAJA DEL BYTE, la parte alta la hacemos "cero"
movwf LCDcaracter
rlf LCDcaracter,W
movwf LCDcaracter
rlf LCDcaracter,W
movwf LCDcaracter
rlf LCDcaracter,W
movwf LCDcaracter
rlf LCDcaracter,W
movwf LCDcaracter
movf PORTC,W
andlw b"00001111"
iorwf LCDcaracter,W
movwf PORTC
BCF PORTE,1 ; LCD E-line Low
RETURN
;-------------------------------------------------------------------------------------------
;
; Rutinas interesantes para la utilización del display LCD
;
;-------------------------------------------------------------------------------------------
LINEA1
movlw b"10000000"
CALL LCDPUTCMD
movlw b"00000000"
CALL LCDPUTCMD
RETURN
LINEA2
movlw b"11000000"
CALL LCDPUTCMD
movlw b"00000000"
CALL LCDPUTCMD
RETURN
LCDCLEAR
movlw b"00000000"
CALL LCDPUTCMD
movlw b"00010000"
CALL LCDPUTCMD
RETURN
CURSOR_IZQ
movlw b"00010000"
CALL LCDPUTCMD
movlw b"00000000"
CALL LCDPUTCMD
return
CURSOR_DER
movlw b"00010000"
CALL LCDPUTCMD
movlw b"01000000"
CALL LCDPUTCMD
return
;*****************************************************************************
; Delay_time = ((DELAY_value * 3) + 4) * Cycle_time
; DELAY_value = (Delay_time - (4 * Cycle_time)) / (3 * Cycle_time)
;
; i.e. (@ 4MHz crystal)
; Delay_time = ((32 * 3) + 4) * 1uSec
; = 100uSec
; DELAY_value = (500uSec - 4) / 3
; = 165.33
; = 165
;*****************************************************************************
DELAY500 ; ESTO SON 0.5 ms
MOVLW .165 ; +1 1 cycle
MOVWF DELAY ; +2 1 cycle
DELAY500_LOOP DECFSZ DELAY, F ; step 1 1 cycle
GOTO DELAY500_LOOP ; step 2 2 cycles
DELAY500_END RETURN ; +3 2 cycles
X_DELAY500
MOVWF X_DELAY ; +1 1 cycle
X_DELAY500_LOOP CALL DELAY500 ; step1 wait 500uSec
DECFSZ X_DELAY, F ; step2 1 cycle
GOTO X_DELAY500_LOOP ; step3 2 cycles
X_DELAY500_END RETURN
A ver si con esto puedes sacar algo en claro, SUERTE!
Un saludo desde Alicante.