# Problema con programa LCD a través de 4 Bit con 16f877A



## jam0_0 (Dic 11, 2008)

Hola a toda la comunidad, en primer lugar agradecerles por todo lo que postean y toda la ayuda que brindan.

El problema que tengo es con un programa para displayar un mensaje en un LCD, lo simulé en proteus y todo OK, luego lo monté en un protoboard, luego en una placa y nada, parece que el LCD no inicializa porque con o sin PIC moviendo el contraste pues aparece la primera linea toda oscura, he revisado los pines y si está bien la parte electrica, parece que tengo un problema en la parte de programación, he probado con 2 pic y el resultado es el mismo, así que no puede ser un pic dañado. Les voy a adjuntar el codigo del archivo asm para que me puedan ayudar y decirme cual o cuales pueden ser los errores que estoy cometiendo:

Gracias de antemano por su ayuda; porsiacaso los puertos están descritos en el programa

Saludos


```
list P = 16F877
#include"p16F877.inc"
#include"lcd_1.inc"
__config 3F31h

;EN ESTE PUNTO HACER UNA PEQUEÑA APLICACION DE UTILIZACION  DE MACROS
;*******************************************
;	4 BIT LCD interface with PIC16F877A	
;	only port D is implemented
;	RD7-RD4 = DB7-DB4  ; RD3=E ; RD0=RS
;
;*******************************************		

	BIT_E	EQU		3
	BIT_RW	EQU		2
	BIT_RS	EQU		0

	CBLOCK	0X0C	;es 0c
	  TEMP	
	  V_DLY	
	  V_DLY1	
	  PDel0  
	  PDel1   
	ENDC  


		org 00  ;start of program at
		goto	START
		org 05

START	

		bsf	STATUS,RP0 	;sellect bank 1
		movlw	b'00000000'
		movwf	TRISD		;set as output
		bcf 	STATUS,RP0 	;select bank 0
		clrf	PORTD			
		
		CALL	INITLCD		;initialize LCD SIS 4 BIT NO CULSOR 
						
		MOVLW	0x41		;H;Write to DDRAM which is displayed in LCD, DDRAM already sellected at initialization
		CALL	LCDWRITE	
		
		MOVLW	"O"		
		CALL	LCDWRITE
		
		MOVLW	"L"		
		CALL	LCDWRITE
		
		MOVLW	"A"		
		CALL	LCDWRITE
		
		MOVLW	" "		
		CALL	LCDWRITE
		
		MOVLW	'M'		
		CALL	LCDWRITE
		
		MOVLW	"U"		
		CALL	LCDWRITE
		
		MOVLW	"M"		
		CALL	LCDWRITE
		
		MOVLW	"D"		
		CALL	LCDWRITE
		
		MOVLW	"O"		
		CALL	LCDWRITE

		MOVLW	" "		
		CALL	LCDWRITE

		MOVLW	" "		
		CALL	LCDWRITE

loop		goto	loop
				

;----------AREA DE LAS SUBRRUTINAS--------------------------
LCDWRITE		;Writes data/character in W register to sellected CG/DD RAM,
			; see its use in START routine
		MOVWF	TEMP
		CALL	DEL_5mS
		MOVF	TEMP,W
		ANDLW	B'11110000'
		IORLW	B'00001001'	;BIT_E=1,BIT_RW=0,BIT_RS=1
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;1 CYCLE COMPLETE
		CALL	DEL_5mS
		SWAPF	TEMP,W		;SWAP NIBBLES AND STORE IN W REGISTER
		ANDLW	B'11110000'
		IORLW	B'00001001'	;BIT_E=1,BIT_RW=0,BIT_RS=1
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;2 CYCLE COMPLETE
		CALL	DEL_5mS
		
		RETURN

;________________________________________________________________________________
INITLCD					;INITIALIZE LCD
		call	DEL_5mS
		call	DEL_5mS
		call	DEL_5mS
		call	DEL_5mS
		call	DEL_5mS

		MOVLW	B'00001000'	;Display Clear 1fr
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;2 CYCLE
		CALL	DEL_5mS		;RETARDO DE 5mS	

		MOVLW	B'00011000'	; Display Clear 2nd
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;1 CYCLY
		CALL	DEL_5mS	
		CALL	DEL_5mS			

		MOVLW	B'00101000'	;Funcion a modo de 4 Bit	
		MOVWF	PORTD
		BCF	PORTD,BIT_E	; BIT_E = LOW NIBEL CERO
		CALL	DEL_5mS		;RETARDO DE 5mS	

		MOVLW	B'00000001'	; Display mode set
		MOVWF	PORTD
		BCF	PORTD,BIT_E	; BIT_E = LOW NIBEL CERO
		CALL	DEL_5mS		;RETARDO DE 5mS	


		MOVLW	B'00101000'	; Display mode set es 
		MOVWF	PORTD
		BCF	PORTD,BIT_E	; BIT_E = LOW NIBEL CERO
		CALL	DEL_5mS		;RETARDO DE 5mS	

		MOVLW	B'00001000'	; 1 linea display ON es 
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;BIT_E=LOW	
		CALL	DEL_5mS		;RETARDO DE 5mS	

		MOVLW	B'00001000'	;Display ON OFF Function
		MOVWF	PORTD
		BCF	PORTD,BIT_E
		CALL	DEL_5mS	

		MOVLW	B'11001000'	;Display ON Curson ON Blink ON
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;1 CYCLE COMPLETE
		CALL	DEL_5mS		

		MOVLW	B'00001000'	;Display Clear 1fr
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;2 CYCLE
		CALL	DEL_5mS		;RETARDO DE 5mS	

		MOVLW	B'00011000'	; Display Clear 2nd
		MOVWF	PORTD
		BCF	PORTD,BIT_E	;1 CYCLY
		CALL	DEL_5mS	
		CALL	DEL_5mS	

		MOVLW	B'00001000'	;Entry Mode SET
		MOVWF	PORTD		;AND BIT_E=1,BIT_RW=0,BIT_RS=0
		BCF	PORTD,BIT_E	;2 CYCLE
		CALL	DEL_5mS		;CLEAR DISPLAY AND HOME CURSOR

		MOVLW	B'01101000'	;Increment Mode Shift OFF	
		MOVWF	PORTD
		BCF	PORTD,BIT_E
		CALL	DEL_5mS		

;;		MOVLW	B'00011000'
;;		MOVWF	PORTD
;;		CALL	DEL_5mS
;;		BCF	PORTD,BIT_E
;;		CALL	DEL_5mS		;RETARDO DE 5mS	-ENTRY SET - 
;;		
;;		MOVLW	B'00001000'	; BIT_E=1,BIT_RW=0,BIT_RS=0
;;		MOVWF	PORTD
;;		CALL	DEL_5mS
;;		BCF	PORTD,BIT_E	;1 CYCLE
;;		CALL	DEL_5mS		
;;
;;		MOVLW	B'01101000'	;ENTRY SET - INCREMENT,NO DISP SHIFT(CUR SHIFT)
;;		MOVWF	PORTD		;BIT_E=1,BIT_RW=0,BIT_RS=0
;;		CALL	DEL_5mS
;;		BCF	PORTD,BIT_E	;2 CYCLE
;;		CALL	DEL_5mS		;RETARDO DE 5mS	-ENTRY SET - 
;;			
;;
		RETURN
;-------------------------------------------------------------
; Code generated by PDEL  ver 1.0  on 05/03/2007 at 07:18:03 p.m.
; Description: Waits 5000 cycles
;-------------------------------------------------------------
DEL_5mS  movlw     .250        ; 1 set number of repetitions (B) es 6
        movwf     PDel0     ; 1 |
PLoop1  movlw     .207      ; 1 set number of repetitions (A) es 207
        movwf     PDel1     ; 1 |
PLoop2  clrwdt              ; 1 clear watchdog
        decfsz    PDel1, 1  ; 1 + (1) is the time over? (A)
        goto      PLoop2    ; 2 no, loop
        decfsz    PDel0,  1 ; 1 + (1) is the time over? (B)
        goto      PLoop1    ; 2 no, loop
PDelL1  goto PDelL2         ; 2 cycles delay
PDelL2  clrwdt              ; 1 cycle delay
        return              ; 2+2 Done
;-------------------------------------------------------------

	END
```


----------



## tiopepe123 (Dic 11, 2008)

Lo mas habitual es pasarse de vueltas, la LCD es muy lenta, añadele retardos.

Haz una subrutina (call) con bastantes nop o un bucle y lo añades a cada transicion de patillas.

Mira en el datasheet y encontraras el tiempo minimo, pero mejor ahora llenar el programa de retoardos y asegurarse que funciona aunque sea leeeento, luego ya lo optimizaras.


----------



## jam0_0 (Dic 11, 2008)

Hola TIOPEPE, gracias por responder, seguí tu indicación, le coloque retardos, en el proteus funciona lentísimo pero cuando lo quemo en el pic no aparece nada, se enciende el backlight (que no es programa sino circuitería) y cuando le doy contraste se ilumina la primera fila pero sin mostrar nada osea todo en negro, igual sucede sin el pic osea que ni siquiera está inicializando el LCD; le he probado voltajes y si está enviando la señal a los pinea adecuados y todo ok, tambien proble con otro pic y con otro lcd y lo mismo, osea que no es ni pic ni lcd, como comenté, los voltajes son correctos así que lo mas seguro es la programación pero noc que pueda ser es por eso que derrepente alguien sabe que error estoy cometiendo en el código

Saludos y gracias


----------



## Leon Elec (Dic 11, 2008)

Esta rutina funciona muy bien pero es para bus de 8.

Saludos.


----------



## Moyano Jonathan (Dic 11, 2008)

yo tengo una rutina de un para que el lcd funcione con tan solo 3 pines para el control. Pero la librería esta en C de CCS si la querés te la paso. Yo la he probado personalmente la librería y funciona pero lo hace de manera un poco lenta por los retardos.


----------



## jam0_0 (Dic 11, 2008)

'Hola, gracias a Jonathan y a Leon por Responder, encontré un error en el código, en las primeras lineas, el cual hace referencia a una dirección ocupada por otros registros en el 16f877 los cuales con: el TMR0 por ejemplo que están a partir de la direcc 0X0C, es por ello que movi el inicio a 0X20 y pues ahí no hay problema con ningún registro de configuración, con eso esperaba que funcionara, pues bien, en el proteus todo ok pero nuevamente lo vuelvo a quemar en ambos pics y el resultado fue igual, sinceramente está siendo frustrante esto porque con error que logro dar el resultado es el mismo, estoy siguiendo la rutina de inicialización con el datasheet del fabricante pero noc en que estoy fallando; alguien tenga una rutina de inicialización para 4 bits porfa para tener una guía, porque no logro dar con el problema real.
Saludos


----------



## Leon Elec (Dic 11, 2008)

Encontré esto en la WEB pero no lo probé. Aseguran que anda.


```
;**************************** Librería "LCD_4BIT.INC" ***********************************
;
;	===================================================================
;	  Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS"
;	  E. Palacios, F. Remiro y L. López.
; 	  Editorial Ra-Ma.  [url]www.ra-ma.es[/url]
;	===================================================================
;
; Estas subrutinas permiten realizar las tareas básicas de control de un módulo LCD de 2
; líneas por 16 caracteres, compatible con el modelo LM016L.
;
; El visualizador LCD está conectado al Puerto B del PIC mediante un bus de 4 bits. Las
; conexiones son:
;    -	Las 4 líneas superiores del módulo LCD, pines <DB7B4>  se conectan a las 4
;	líneas superiores del Puerto B del PIC, pines <RD7:RD4>.
;    -	Pin RS del LCD a la línea RA0 del PIC.
;    -	Pin R/W del LCD a la línea RA1 del PIC, o a masa.
;    -	Pin Enable del LCD a la línea RA2 del PIC.
;
; Se utilizan llamadas a subrutinas de retardo de tiempo localizadas en la librería RETARDOS.INC.
;
; ZONA DE DATOS *********************************************************************

	CBLOCK			0x23
	LCD_Dato
	LCD_GuardaDato
	LCD_GuardaTRISD
	LCD_Auxiliar1
	LCD_Auxiliar2
	ENDC

LCD_CaracteresPorLinea	EQU	.20	; Número de caracteres por línea de la pantalla.

#DEFINE  LCD_PinRS	PORTD,0
#DEFINE  LCD_PinRW	PORTD,1
#DEFINE  LCD_PinEnable	PORTD,2
#DEFINE  LCD_BusDatos	PORTD

; Subrutina "LCD_Inicializa" ------------------------------------------------------------
;
; Inicialización del módulo LCD: Configura funciones del LCD, produce reset por software,
; borra memoria y enciende pantalla. El fabricante especifica que para garantizar la
; configuración inicial hay que hacerla como sigue:
;
LCD_Inicializa
    	call	Retardo_5ms
	banksel TRISD		; Configura las líneas conectadas al pines RS,
	movlw	b'00000000'
	movwf	TRISD
	clrf	STATUS
	bcf	LCD_PinRW		; En caso de que esté conectado le indica
					; que se va a escribir en el LCD.
	bcf	LCD_PinEnable		; Impide funcionamiento del LCD poniendo E=0.
	bcf 	LCD_PinRS		; Activa el Modo Comando poniendo RS=0.
	call	Retardo_20ms
	movlw	b'00110000'	
	call	LCD_EscribeLCD		; Escribe el dato en el LCD.
	call	Retardo_5ms	
	movlw	b'00110000'	
	call	LCD_EscribeLCD
	call	Retardo_200micros
	movlw	b'00110000'	
	call	LCD_EscribeLCD
	call	Retardo_200micros
	movlw	b'00100000'		; Interface de 4 bits.
	call	LCD_EscribeLCD

; Ahora configura el resto de los parámetros: 

	call	LCD_2Lineas4Bits5x7	; LCD de 2 líneas y caracteres de 5x7 puntos.
	call	LCD_Borra		; Pantalla encendida y limpia. Cursor al principio
	call	LCD_CursorOFF		; de la línea 1. Cursor apagado.
	call	LCD_CursorIncr		; Cursor en modo incrementar.
	return

; Subrutina "LCD_EscribeLCD" -----------------------------------------------------------
;
; Envía el dato del registro de trabajo W al bus de dato y produce un pequeño pulso en el pin
; Enable del LCD. Para no alterar el contenido de las líneas de la parte baja del Puerto B que
; no son utilizadas para el LCD (pines RB3:RB0), primero se lee estas líneas y después se
; vuelve a enviar este dato sin cambiarlo.

LCD_EscribeLCD
	andlw	b'11110000'		; Se queda con el nibble alto del dato que es el
	movwf	LCD_Dato		; que hay que enviar y lo guarda.
	movf	LCD_BusDatos,W		; Lee la información actual de la parte baja
	andlw	b'00001111'		; del Puerto B, que no se debe alterar.
	iorwf	LCD_Dato,F		; Enviará la parte alta del dato de entrada
					; y en la parte baja lo que había antes.
	banksel TRISD		; Acceso al Banco 1.
	movf	TRISD,W		; Guarda la configuración que tenía antes TRISD.
    banksel	PORTD
	movwf	LCD_GuardaTRISD
    banksel	TRISD
	movlw	b'00001111'		; Las 4 líneas inferiores del Puerto B se dejan 
	andwf	PORTD,F			; como estaban y las 4 superiores como salida.
	clrf	STATUS		; Acceso al Banco 0.
;
	movf	LCD_Dato,W		; Recupera el dato a enviar.
	movwf	LCD_BusDatos		; Envía el dato al módulo LCD.
	bsf	LCD_PinEnable		; Permite funcionamiento del LCD mediante un pequeño
	nop
	bcf	LCD_PinEnable		; pulso y termina impidiendo el funcionamiento del LCD.
	;banksel TRISD		; Acceso al Banco 1. Restaura el antiguo valor en
    banksel	PORTD
	movf	LCD_GuardaTRISD,W	; la configuración del Puerto B.
    banksel	TRISD
	movwf	TRISD			; 
	clrf	STATUS		; Acceso al Banco 0.
	return

; Subrutinas variadas para el control del módulo LCD -----------------------------------------
;
;Los comandos que pueden ser ejecutados son:
;
LCD_CursorIncr				; Cursor en modo incrementar.
	movlw	b'00000110'
	goto	LCD_EnviaComando
LCD_Linea1 				; Cursor al principio de la Línea 1.
	movlw	b'10000000' 		; Dirección 00h de la DDRAM
	goto	LCD_EnviaComando
LCD_Linea2 				; Cursor al principio de la Línea 2.
	movlw	b'11000000' 		; Dirección 40h de la DDRAM
	goto	LCD_EnviaComando 
LCD_Linea3 				; Cursor al principio de la Línea 3
	movlw	b'10010100' 		; Dirección 14h de la DDRAM
	goto	LCD_EnviaComando 
LCD_Linea4 				; Cursor al principio de la Línea 4
	movlw	b'11010100' 		; Dirección 54h de la DDRAM
	goto	LCD_EnviaComando 
LCD_PosicionLinea1			; Cursor a posición de la Línea 1, a partir de la
	iorlw	b'10000000'		; dirección 00h de la DDRAM más el valor del
	goto	LCD_EnviaComando	; registro W.
LCD_PosicionLinea2			; Cursor a posición de la Línea 2, a partir de la
	iorlw	b'11000000'		; dirección 40h de la DDRAM más el valor del
	goto	LCD_EnviaComando	; registro W.
LCD_PosicionLinea3			; Cursor a posición de la Línea 3, a partir de la
	iorlw	b'10010100'		; dirección 00h de la DDRAM más el valor del
	goto	LCD_EnviaComando	; registro W.
LCD_PosicionLinea4			; Cursor a posición de la Línea 4, a partir de la
	iorlw	b'11010100'		; dirección 40h de la DDRAM más el valor del
	goto	LCD_EnviaComando	; registro W.
LCD_OFF				; Pantalla apagada.
	movlw	b'00001000'
	goto	LCD_EnviaComando
LCD_CursorON				; Pantalla encendida y cursor encendido.
	movlw	b'00001110'
	goto	LCD_EnviaComando
LCD_CursorOFF				; Pantalla encendida y cursor apagado.
	movlw	b'00001100'
	goto	LCD_EnviaComando
LCD_Borra				; Borra toda la pantalla, memoria DDRAM y pone el 
	movlw	b'00000001'		; cursor a principio de la línea 1.
	goto	LCD_EnviaComando
LCD_2Lineas4Bits5x7			; Define la pantalla de 2 líneas, con caracteres
	movlw	b'00101000'		; de 5x7 puntos y conexión al PIC mediante bus de
;	goto	LCD_EnviaComando	; 4 bits. 

; Subrutinas "LCD_EnviaComando" y "LCD_Caracter" ------------------------------------
;
; "LCD_EnviaComando". Escribe un comando en el registro del módulo LCD. La palabra de
; comando ha sido entregada a través del registro W.  Trabaja en Modo Comando.
; "LCD_Caracter". Escribe en la memoria DDRAM del LCD el carácter ASCII introducido a
; a través del registro W. Trabaja en Modo Dato.
;
LCD_EnviaComando
	bcf	LCD_PinRS		; Activa el Modo Comando, poniendo RS=0.
	goto	LCD_Envia
LCD_Caracter
	bsf	LCD_PinRS		; Activa el "Modo Dato", poniendo RS=1.
	call	LCD_CodigoCGROM	; Obtiene el código para correcta visualización.
LCD_Envia
	movwf	LCD_GuardaDato		; Guarda el dato a enviar.
	call	LCD_EscribeLCD		; Primero envía el nibble alto.
	swapf	LCD_GuardaDato,W	; Ahora envía el nibble bajo. Para ello pasa el
					; nibble bajo del dato a enviar a parte alta del byte.
	call	LCD_EscribeLCD		; Se envía al visualizador LCD.
	btfss	LCD_PinRS		; Debe garantizar una correcta escritura manteniendo 
	call	Retardo_2ms		; 2 ms en modo comando y 50 µs en modo cáracter.
	call	Retardo_50micros
	return	

; Subrutina "LCD_CodigoCGROM" -----------------------------------------------------------
;
; A partir del carácter ASCII número 127 los códigos de los caracteres definidos en la
; tabla CGROM del LM016L no coinciden con los códigos ASCII. Así por ejemplo, el código
; ASCII de la "Ñ" en la tabla CGRAM del LM016L es EEh.
;
; Esta subrutina convierte los códigos ASCII de la "Ñ", "º" y otros, a códigos CGROM para que
; que puedan ser visualizado en el módulo LM016L.
; 
; Entrada:	En (W) el código ASCII del carácter que se desea visualizar.
; Salida:	En (W) el código definido en la tabla CGROM.

LCD_CodigoCGROM
	movwf	LCD_Dato		; Guarda el valor del carácter y comprueba si es
LCD_EnheMinuscula			; un carácter especial.
	sublw	'ñ' 			; ¿Es la "ñ"?
	btfss	STATUS,Z
	goto	LCD_EnheMayuscula	; No es "ñ".
	movlw	b'11101110'		; Código CGROM de la "ñ".
	movwf	LCD_Dato
	goto	LCD_FinCGROM
LCD_EnheMayuscula
	movf	LCD_Dato,W		; Recupera el código ASCII de entrada.
	sublw	'Ñ' 			; ¿Es la "Ñ"?
	btfss	STATUS,Z
	goto	LCD_Grado		; No es "Ñ".
	movlw	b'11101110'		; Código CGROM de la "ñ". (No hay símbolo para
	movwf	LCD_Dato		; la "Ñ" mayúscula en la CGROM).
	goto	LCD_FinCGROM	
LCD_Grado
	movf	LCD_Dato,W		; Recupera el código ASCII de entrada.
	sublw	'º' 			; ¿Es el símbolo "º"?
	btfss	STATUS,Z
	goto	LCD_FinCGROM		; No es "º".
	movlw	b'11011111'		; Código CGROM del símbolo "º".
	movwf	LCD_Dato
	
LCD_FinCGROM
	movf	LCD_Dato,W		; En (W) el código buscado.
	return

; Subrutina "LCD_DosEspaciosBlancos" y "LCD_LineaBlanco" --------------------------------
;
; Visualiza espacios en blanco.

LCD_LineaEnBlanco
	movlw	LCD_CaracteresPorLinea
	goto	LCD_EnviaBlancos
LCD_UnEspacioBlanco
	movlw	.1
	goto	LCD_EnviaBlancos
LCD_DosEspaciosBlancos
	movlw	.2
	goto	LCD_EnviaBlancos
LCD_TresEspaciosBlancos
	movlw	.3
LCD_EnviaBlancos
	movwf	LCD_Auxiliar1		; (LCD_Auxiliar1) se utiliza como contador.
LCD_EnviaOtroBlanco	
	movlw	' '			; Esto es un espacio en blanco.
	call	LCD_Caracter		; Visualiza tanto espacios en blanco como se
	decfsz	LCD_Auxiliar1,F		; haya cargado en (LCD_Auxiliar1).
	goto	LCD_EnviaOtroBlanco
	return

; Subrutinas "LCD_ByteCompleto" y "LCD_Byte" --------------------------------------------
;
; Subrutina "LCD_ByteCompleto", visualiza el byte que almacena el registro W en el
; lugar actual de la pantalla. Por ejemplo, si (W)=b'10101110' visualiza "AE".
;
; Subrutina "LCD_Byte" igual que la anterior, pero en caso de que el nibble alto sea cero 
; visualiza en su lugar un espacio en blanco. Por ejemplo si (W)=b'10101110' visualiza "AE"
; y si (W)=b'00001110', visualiza " E" (un espacio blanco delante).
;
; Utilizan la subrutina "LCD_Nibble" que se analiza más adelante.
;
LCD_Byte
	movwf	LCD_Auxiliar2		; Guarda el valor de entrada.
	andlw	b'11110000'		; Analiza si el nibble alto es cero.
	btfss	STATUS,Z		; Si es cero lo apaga.
	goto	LCD_VisualizaAlto		; No es cero y lo visualiza.
	movlw	' '			; Visualiza un espacio en blanco.
	call	LCD_Caracter
	goto	LCD_VisualizaBajo

LCD_ByteCompleto
	movwf	LCD_Auxiliar2		; Guarda el valor de entrada.
LCD_VisualizaAlto
	swapf	LCD_Auxiliar2,W		; Pone el nibble alto en la parte baja.
	call	LCD_Nibble		; Lo visualiza.
LCD_VisualizaBajo
	movf	LCD_Auxiliar2,W		; Repite el proceso con el nibble bajo.
;	call	LCD_Nibble		; Lo visualiza.
;	return

; Subrutina "LCD_Nibble" ----------------------------------------------------------------
;
; Visualiza en el lugar actual de la pantalla, el valor hexadecimal que almacena en el nibble
; bajo del registro W. El nibble alto de W no es tenido en cuenta. Ejemplos:
; - Si (W)=b'01010110', se visualizará "6". 
; - Si (W)=b'10101110', se visualizará "E". 
;
LCD_Nibble
	andlw	b'00001111'		; Se queda con la parte baja.
	movwf	LCD_Auxiliar1		; Lo guarda.
	sublw	0x09			; Comprueba si hay que representarlo con letra.
	btfss	STATUS,C	
	goto	LCD_EnviaByteLetra
	movf	LCD_Auxiliar1,W
	addlw	'0'			; El número se pasa a carácter ASCII sumándole
	goto 	LCD_FinVisualizaDigito	; el ASCII del cero y lo visualiza.
LCD_EnviaByteLetra
	movf	LCD_Auxiliar1,W
	addlw	'A'-0x0A			; Sí, por tanto, se le suma el ASCII de la 'A'.
LCD_FinVisualizaDigito
	goto	LCD_Caracter		; Y visualiza el carácter. Se hace con un "goto"
					; para no sobrecargar la pila.
```
Y este es la rutina retardos.inc

```
;**************************** Librería "RETARDOS.INC" ********************************* 
; 
;    =================================================================== 
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS" 
;      E. Palacios, F. Remiro y L. López. 
;       Editorial Ra-Ma.  [url]www.ra-ma.es[/url] 
;    =================================================================== 
; 
; Librería con múltiples subrutinas de retardos, desde 4 microsegundos hasta 20 segundos. 
; Además se pueden implementar otras subrutinas muy fácilmente. 
; 
; Se han calculado para un sistema microcontrolador con un PIC trabajando con un cristal 
; de cuarzo a 4 MHz. Como cada ciclo máquina son 4 ciclos de reloj, resulta que cada 
; ciclo máquina tarda 4 x 1/4MHz = 1 µs. 
; 
; En los comentarios, "cm" significa "ciclos máquina". 
; 
; ZONA DE DATOS ********************************************************************* 

    CBLOCK 
    R_ContA                ; Contadores para los retardos. 
    R_ContB 
    R_ContC 
    ENDC 
; 
; RETARDOS de 4 hasta 10 microsegundos --------------------------------------------------- 
; 
; A continuación retardos pequeños teniendo en cuenta que para una frecuencia de 4 MHZ, 
; la llamada a subrutina "call" tarda 2 ciclos máquina, el retorno de subrutina 
; "return" toma otros 2 ciclos máquina y cada instrucción "nop" tarda 1 ciclo máquina. 
; 
Retardo_10micros                ; La llamada "call" aporta 2 ciclos máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    nop                ; Aporta 1 ciclo máquina. 
Retardo_5micros                ; La llamada "call" aporta 2 ciclos máquina. 
    nop                ; Aporta 1 ciclo máquina. 
Retardo_4micros                ; La llamada "call" aporta 2 ciclos máquina. 
    return                ; El salto del retorno aporta 2 ciclos máquina. 
; 
; RETARDOS de 20 hasta 500 microsegundos ------------------------------------------------ 
; 
Retardo_500micros                ; La llamada "call" aporta 2 ciclos máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    movlw    d'164'            ; Aporta 1 ciclo máquina. Este es el valor de "K". 
    goto    RetardoMicros        ; Aporta 2 ciclos máquina. 
Retardo_200micros                ; La llamada "call" aporta 2 ciclos máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    movlw    d'64'            ; Aporta 1 ciclo máquina. Este es el valor de "K". 
    goto    RetardoMicros        ; Aporta 2 ciclos máquina. 
Retardo_100micros                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'31'            ; Aporta 1 ciclo máquina. Este es el valor de "K". 
    goto    RetardoMicros        ; Aporta 2 ciclos máquina. 
Retardo_50micros                ; La llamada "call" aporta 2 ciclos máquina. 
    nop                ; Aporta 1 ciclo máquina. 
    movlw    d'14'            ; Aporta 1 ciclo máquina. Este es el valor de "K". 
    goto    RetardoMicros        ; Aporta 2 ciclos máquina. 
Retardo_20micros                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'5'            ; Aporta 1 ciclo máquina. Este es el valor de "K". 
; 
; El próximo bloque "RetardoMicros" tarda: 
; 1 + (K-1) + 2 + (K-1)x2 + 2 = (2 + 3K) ciclos máquina. 
; 
RetardoMicros 
    movwf    R_ContA            ; Aporta 1 ciclo máquina. 
Rmicros_Bucle 
    decfsz    R_ContA,F        ; (K-1)x1 cm (cuando no salta) + 2 cm (al saltar). 
    goto    Rmicros_Bucle        ; Aporta (K-1)x2 ciclos máquina. 
    return                ; El salto del retorno aporta 2 ciclos máquina. 
; 
;En total estas subrutinas tardan: 
; - Retardo_500micros:    2 + 1 + 1 + 2 + (2 + 3K) = 500 cm = 500 µs. (para K=164 y 4 MHz). 
; - Retardo_200micros:    2 + 1 + 1 + 2 + (2 + 3K) = 200 cm = 200 µs. (para K= 64 y 4 MHz). 
; - Retardo_100micros:    2     + 1 + 2 + (2 + 3K) = 100 cm = 100 µs. (para K= 31 y 4 MHz). 
; - Retardo_50micros :    2 + 1 + 1 + 2 + (2 + 3K) =  50 cm =  50 µs. (para K= 14 y 4 MHz). 
; - Retardo_20micros :    2     + 1     + (2 + 3K) =  20 cm =  20 µs. (para K=  5 y 4 MHz). 
; 
; RETARDOS de 1 ms hasta 200 ms. -------------------------------------------------------- 
; 
Retardo_200ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'200'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_100ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'100'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_50ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'50'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_20ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'20'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_10ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'10'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_5ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'5'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_2ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'2'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
    goto    Retardos_ms        ; Aporta 2 ciclos máquina. 
Retardo_1ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'1'            ; Aporta 1 ciclo máquina. Este es el valor de "M". 
; 
; El próximo bloque "Retardos_ms" tarda: 
; 1 + M + M + KxM + (K-1)xM + Mx2 + (K-1)Mx2 + (M-1) + 2 + (M-1)x2 + 2 = 
; = (2 + 4M + 4KM) ciclos máquina. Para K=249 y M=1 supone 1002 ciclos máquina 
; que a 4 MHz son 1002 µs = 1 ms. 
; 
Retardos_ms 
    movwf    R_ContB            ; Aporta 1 ciclo máquina. 
R1ms_BucleExterno 
    movlw    d'249'            ; Aporta Mx1 ciclos máquina. Este es el valor de "K". 
    movwf    R_ContA            ; Aporta Mx1 ciclos máquina. 
R1ms_BucleInterno 
    nop                ; Aporta KxMx1 ciclos máquina. 
    decfsz    R_ContA,F        ; (K-1)xMx1 cm (cuando no salta) + Mx2 cm (al saltar). 
    goto    R1ms_BucleInterno        ; Aporta (K-1)xMx2 ciclos máquina. 
    decfsz    R_ContB,F        ; (M-1)x1 cm (cuando no salta) + 2 cm (al saltar). 
    goto    R1ms_BucleExterno     ; Aporta (M-1)x2 ciclos máquina. 
    return                ; El salto del retorno aporta 2 ciclos máquina. 
; 
;En total estas subrutinas tardan: 
; - Retardo_200ms:    2 + 1 + 2 + (2 + 4M + 4KM) = 200007 cm = 200 ms. (M=200 y K=249). 
; - Retardo_100ms:    2 + 1 + 2 + (2 + 4M + 4KM) = 100007 cm = 100 ms. (M=100 y K=249). 
; - Retardo_50ms :    2 + 1 + 2 + (2 + 4M + 4KM) =  50007 cm =  50 ms. (M= 50 y K=249). 
; - Retardo_20ms :    2 + 1 + 2 + (2 + 4M + 4KM) =  20007 cm =  20 ms. (M= 20 y K=249). 
; - Retardo_10ms :    2 + 1 + 2 + (2 + 4M + 4KM) =  10007 cm =  10 ms. (M= 10 y K=249). 
; - Retardo_5ms  :    2 + 1 + 2 + (2 + 4M + 4KM) =   5007 cm =   5 ms. (M=  5 y K=249). 
; - Retardo_2ms  :    2 + 1 + 2 + (2 + 4M + 4KM) =   2007 cm =   2 ms. (M=  2 y K=249). 
; - Retardo_1ms  :    2 + 1     + (2 + 4M + 4KM) =   1005 cm =   1 ms. (M=  1 y K=249). 
; 
; RETARDOS de 0.5 hasta 20 segundos --------------------------------------------------- 
; 
Retardo_20s                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'200'            ; Aporta 1 ciclo máquina. Este es el valor de "N". 
    goto    Retardo_1Decima        ; Aporta 2 ciclos máquina. 
Retardo_10s                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'100'            ; Aporta 1 ciclo máquina. Este es el valor de "N". 
    goto    Retardo_1Decima        ; Aporta 2 ciclos máquina. 
Retardo_5s                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'50'            ; Aporta 1 ciclo máquina. Este es el valor de "N". 
    goto    Retardo_1Decima        ; Aporta 2 ciclos máquina. 
Retardo_2s                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'20'            ; Aporta 1 ciclo máquina. Este es el valor de "N". 
    goto    Retardo_1Decima        ; Aporta 2 ciclos máquina. 
Retardo_1s                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'10'            ; Aporta 1 ciclo máquina. Este es el valor de "N". 
    goto    Retardo_1Decima        ; Aporta 2 ciclos máquina. 
Retardo_500ms                ; La llamada "call" aporta 2 ciclos máquina. 
    movlw    d'5'            ; Aporta 1 ciclo máquina. Este es el valor de "N". 
; 
; El próximo bloque "Retardo_1Decima" tarda: 
; 1 + N + N + MxN + MxN + KxMxN + (K-1)xMxN + MxNx2 + (K-1)xMxNx2 + 
;   + (M-1)xN + Nx2 + (M-1)xNx2 + (N-1) + 2 + (N-1)x2 + 2 = 
; = (2 + 4M + 4MN + 4KM) ciclos máquina. Para K=249, M=100 y N=1 supone 100011 
; ciclos máquina que a 4 MHz son 100011 µs = 100 ms = 0,1 s = 1 décima de segundo. 
; 
Retardo_1Decima 
    movwf    R_ContC            ; Aporta 1 ciclo máquina. 
R1Decima_BucleExterno2 
    movlw    d'100'            ; Aporta Nx1 ciclos máquina. Este es el valor de "M". 
    movwf    R_ContB            ; Aporta Nx1 ciclos máquina. 
R1Decima_BucleExterno 
    movlw    d'249'            ; Aporta MxNx1 ciclos máquina. Este es el valor de "K". 
    movwf    R_ContA            ; Aporta MxNx1 ciclos máquina. 
R1Decima_BucleInterno           
    nop                ; Aporta KxMxNx1 ciclos máquina. 
    decfsz    R_ContA,F        ; (K-1)xMxNx1 cm (si no salta) + MxNx2 cm (al saltar). 
    goto    R1Decima_BucleInterno    ; Aporta (K-1)xMxNx2 ciclos máquina. 
    decfsz    R_ContB,F        ; (M-1)xNx1 cm (cuando no salta) + Nx2 cm (al saltar). 
    goto    R1Decima_BucleExterno    ; Aporta (M-1)xNx2 ciclos máquina. 
    decfsz    R_ContC,F        ; (N-1)x1 cm (cuando no salta) + 2 cm (al saltar). 
    goto    R1Decima_BucleExterno2    ; Aporta (N-1)x2 ciclos máquina. 
    return                ; El salto del retorno aporta 2 ciclos máquina. 
; 
;En total estas subrutinas tardan: 
; - Retardo_20s:    2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) = 20000807 cm = 20 s. 
;            (N=200, M=100 y K=249). 
; - Retardo_10s:    2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) = 10000407 cm = 10 s. 
;            (N=100, M=100 y K=249). 
; - Retardo_5s:        2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) =  5000207 cm =  5 s. 
;            (N= 50, M=100 y K=249). 
; - Retardo_2s:        2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) =  2000087 cm =  2 s. 
;            (N= 20, M=100 y K=249). 
; - Retardo_1s:        2 + 1 + 2 + (2 + 4N + 4MN + 4KMN) =  1000047 cm =  1 s. 
;            (N= 10, M=100 y K=249). 
; - Retardo_500ms:    2 + 1     + (2 + 4N + 4MN + 4KMN) =   500025 cm = 0,5 s. 
;            (N=  5, M=100 y K=249). 

;    =================================================================== 
;      Del libro "MICROCONTROLADOR PIC16F84. DESARROLLO DE PROYECTOS" 
;      E. Palacios, F. Remiro y L. López. 
;       Editorial Ra-Ma.  [url]www.ra-ma.es[/url] 
;    ===================================================================
```

De todas maneras, aquí los tienes adjuntados


----------



## Moyano Jonathan (Dic 11, 2008)

yo las probé y funcionan.


----------



## jam0_0 (Dic 12, 2008)

Ok, gracias, los voy a ver y probar y en base a eso veo mi programa porque lo tengo que hacer en base a mi programa, les comento como me fue
Saludos


----------



## jam0_0 (Dic 12, 2008)

Gracias Leon_Elec por los codigos, pero estás seguro que funciona con esa configuracion? porque pues los puse tal y como me los enviaste y pues no displaya nada en el proteus, estoy intentando revisar si tiene algun error y pues todavía no encuentro alguno mas que una configuración en el pin E que no es el portd2 sino el portd3 pero despues de eso no he encontrado nada mas.

Saludos


----------



## jam0_0 (Dic 13, 2008)

Hola, pues ya logré hacerlo simular en el Proteus, solo faltaba hacerle esa modificación que te comenté Leon Elec: cambiarle el pin del Enable del 2 al 3 en el puerto D pero el resultado sigue siendo igual al programa del post inicial: cuando quemo el pic luego no diaplaya nada, moviendo el contraste, la primera linea se queda oscura solamente; acá les dejo unas fotos para que se den una idea, si alguien ha tenido un problema similar porfa una ayudita para poder salir de esto que me tiene cabezón.

Saludos

PD: Lo que sucede entre una foto y otra es cuando le doy a RESET  por el pin 1 parpadea entre una y otra, espero se pueda ver la diferencia.


----------



## ericklarva (Dic 13, 2008)

Hola jam0 0, podrás postear tu programa de control del LCD que usas actualmente?
Igual hacer énfasis en las conexiones que tienes realizadas a tu LCD. Recordando que tu RW debe estar siempre a GND si no piensas implementarlo.
Saludos


----------



## jam0_0 (Dic 13, 2008)

Hola Erick, pues el programa que he usado es el que he puesto al inicio que si lo simula bien el proteus, tambien he usado el de Leon Elec que tambien lo ssimula bien el proteus pero los resultados en ambos casos son los mismos a los de las fotos y sip el pin de RW siempre está a GND eso si he tenido en cuenta, luego todo lo demas de la parte electrica lo he revisado varias veces, tanto en protoboard como en una placa que hice, es por ello que estoy un tanto frustrado por las malas experiencias que me está llevando esto.
Saludos


----------



## sangreaztk (Dic 14, 2008)

y no será que el LCD ya no funca?
que te presten uno o prueba el tuyo en un programa/hardware de algún compa que ya jale!


----------



## Leon Elec (Dic 14, 2008)

¿me podrías subir como conectaste el LCD al pic? y también sube el programa con la modificación, ah y también el pic que estás utilizando. Así, no trato de tirar soluciones al azar y encarar bien el problema.

Una anegdona. Cuando empeze por primera vez con un LCD, lo hise en el protorboard y no habia forma de hacerlo andar, ¿y cual esra el problema? los condensadores de desacoplo del cristal. Se los saqué y chau problema.

no te olvides de subrime lo que te pido.


----------



## Moyano Jonathan (Dic 14, 2008)

yo para mis primeras prácticas de LCD, utilize un display LCD conectado a un 74HC595 (display serie) y la programación la hice en C de CCS. Me funcionó muy bien , aunque las rutinas implementadas para controlar el lcd de esa forma hicieron que sea un poco lenta la visualización de datos.

Recientemente próbe el código de Leon y funciono a la primera utilizando el esquema del libro pic16f84a desarrollo de proyectos.


----------



## jam0_0 (Dic 14, 2008)

Gracias Jonathan y Leon por responder, pues voy a adjuntar el programa y diseño en proteus de lo que estoy haciendo, tal y como está en el proteus es como he conectado tanto en el proto como en la placa los pines del LCD pues los del pic (que es el 16f877 como está en la simulación) ya saben que no hace falta conectarlos en el proteus, tambien adjunto el programa con las modificaciones y todo, espero puedan dar con el error que estoy cometiendo y ciegamente no lo puedo encontrar.

Saludos

PD porsiacaso en el prgrama asjunto mi direccion de correo (es hotmail)


----------



## jam0_0 (Dic 14, 2008)

Hola sangreaztk, pues no creo que el lcd esté malo porque lo he probado con 3 lcd's y con 2 pics así q es remota la posibilidad que todos ellos estén mal, he permutado entre ellos una y otra vez tambien con los fuses del programa y nada.

Saludos


----------



## ericklarva (Dic 15, 2008)

Hola jam0 0, si todo anda tan frustrante como comentas porque no hacer algo diferente. Intenta manejar otro puerto, al menos para probar, como el puerto B.
Igual conecta LEDs en paralelo con resistencias a los pines de RS y ENABLE del LCD para ver si las señales se activan o desactivan.
Te dejo un código desensamblado de "C" a "asm" para darte una idea diferente del programa.
A cada línea comentada le sigue su código en "asm" con un poco de tiempo puedes amoldarla a tus necesidades.
Suerte.


```
....................  
....................  
....................  
.................... #define  use_portb_kbd TRUE 
.................... #use FAST_IO( A ) 
.................... #use FAST_IO( B ) 
.................... #use FAST_IO( C ) 
.................... #use FAST_IO( D ) 
.................... #use FAST_IO( E ) 
.................... #include <LCD.C> 
.................... /////////////////////////////////////////////////////////////////////////// 
.................... ////                             LCDD.C                                //// 
.................... ////                 Driver for common LCD modules                     //// 
.................... ////                                                                   //// 
.................... ////  lcd_init()   Must be called before any other function.           //// 
.................... ////                                                                   //// 
.................... ////  lcd_putc(c)  Will display c on the next position of the LCD.     //// 
.................... ////                     The following have special meaning:           //// 
.................... ////                      \f  Clear display                            //// 
.................... ////                      \n  Go to start of second line               //// 
.................... ////                      \b  Move back one position                   //// 
.................... ////                                                                   //// 
.................... ////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)    //// 
.................... ////                                                                   //// 
.................... ////  lcd_getc(x,y)   Returns character at position x,y on LCD         //// 
.................... ////                                                                   //// 
.................... /////////////////////////////////////////////////////////////////////////// 
.................... ////        (C) Copyright 1996,2007 Custom Computer Services           //// 
.................... //// This source code may only be used by licensed users of the CCS C  //// 
.................... //// compiler.  This source code may only be distributed to other      //// 
.................... //// licensed users of the CCS C compiler.  No other use, reproduction //// 
.................... //// or distribution is permitted without written permission.          //// 
.................... //// Derivative programs created using this software in object code    //// 
.................... //// form are not restricted in any way.                               //// 
.................... /////////////////////////////////////////////////////////////////////////// 
....................  
.................... // As defined in the following structure the pin connection is as follows: 
.................... //     D0  enable 
.................... //     D1  rs 
.................... //     D2  rw 
.................... //     D4  D4 
.................... //     D5  D5 
.................... //     D6  D6 
.................... //     D7  D7 
.................... // 
.................... //   LCD pins D0-D3 are not used and PIC D3 is not used. 
....................  
.................... // Un-comment the following define to use port B 
.................... // #define use_portb_lcd TRUE 
....................  
....................  
.................... struct lcd_pin_map {                 // This structure is overlayed 
....................            BOOLEAN enable;           // on to an I/O port to gain 
....................            BOOLEAN rs;               // access to the LCD pins. 
....................            BOOLEAN rw;               // The bits are allocated from 
....................            BOOLEAN unused;           // low order up.  ENABLE will 
....................            int     data : 4;         // be pin B0. 
....................         } lcd; 
....................  
....................  
.................... #if defined use_portb_lcd 
....................    //#locate lcd = getenv("sfrORTB")    // This puts the entire structure over the port 
....................    #ifdef __pch__ 
....................     #locate lcd = 0xf81 
....................    #else 
....................     #locate lcd = 6 
....................    #endif 
....................    #define set_tris_lcd(x) set_tris_b(x) 
.................... #else 
....................    //#locate lcd = getenv("sfrORTD")    // This puts the entire structure over the port 
....................    #ifdef __pch__ 
....................     #locate lcd = 0xf83 
....................    #else 
....................     #locate lcd = 8 
....................    #endif 
....................    #define set_tris_lcd(x) set_tris_d(x) 
.................... #endif 
....................  
.................... #ifndef lcd_type 
.................... #define lcd_type 2           // 0=5x7, 1=5x10, 2=2 lines 
.................... #endif 
....................  
.................... #define lcd_line_two 0x40    // LCD RAM address for the second line 
....................  
....................  
.................... BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; 
....................                              // These bytes need to be sent to the LCD 
....................                              // to start it up. 
....................  
....................  
....................                              // The following are used for setting 
....................                              // the I/O port direction register. 
....................  
.................... struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out 
.................... struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in 
....................  
....................  
....................  
.................... BYTE lcd_read_byte() { 
....................       BYTE low,high; 
....................       set_tris_lcd(LCD_READ); 
*
0305:  MOVLW  F0
0306:  BSF    03.5
0307:  MOVWF  08
....................       lcd.rw = 1; 
0308:  BCF    03.5
0309:  BSF    08.2
....................       delay_cycles(1); 
030A:  NOP
....................       lcd.enable = 1; 
030B:  BSF    08.0
....................       delay_cycles(1); 
030C:  NOP
....................       high = lcd.data; 
030D:  MOVF   08,W
030E:  SWAPF  08,W
030F:  ANDLW  0F
0310:  MOVWF  4E
....................       lcd.enable = 0; 
0311:  BCF    08.0
....................       delay_cycles(1); 
0312:  NOP
....................       lcd.enable = 1; 
0313:  BSF    08.0
....................       delay_us(1); 
0314:  NOP
....................       low = lcd.data; 
0315:  MOVF   08,W
0316:  SWAPF  08,W
0317:  ANDLW  0F
0318:  MOVWF  4D
....................       lcd.enable = 0; 
0319:  BCF    08.0
....................       set_tris_lcd(LCD_WRITE); 
031A:  MOVLW  00
031B:  BSF    03.5
031C:  MOVWF  08
....................       return( (high<<4) | low); 
031D:  BCF    03.5
031E:  SWAPF  4E,W
031F:  MOVWF  77
0320:  MOVLW  F0
0321:  ANDWF  77,F
0322:  MOVF   77,W
0323:  IORWF  4D,W
0324:  MOVWF  78
.................... } 
....................  
....................  
.................... void lcd_send_nibble( BYTE n ) { 
....................       lcd.data = n; 
*
02F8:  SWAPF  4E,W
02F9:  ANDLW  F0
02FA:  MOVWF  77
02FB:  MOVLW  0F
02FC:  ANDWF  08,W
02FD:  IORWF  77,W
02FE:  MOVWF  08
....................       delay_cycles(1); 
02FF:  NOP
....................       lcd.enable = 1; 
0300:  BSF    08.0
....................       delay_us(2); 
0301:  GOTO   302
....................       lcd.enable = 0; 
0302:  BCF    08.0
.................... } 
0303:  RETLW  00
....................  
....................  
.................... void lcd_send_byte( BYTE address, BYTE n ) { 
....................  
....................       lcd.rs = 0; 
0304:  BCF    08.1
....................       while ( bit_test(lcd_read_byte(),7) ) ; 
*
0325:  MOVF   78,W
0326:  MOVWF  4D
0327:  BTFSC  4D.7
0328:  GOTO   305
....................       lcd.rs = address; 
0329:  BTFSS  4B.0
032A:  BCF    08.1
032B:  BTFSC  4B.0
032C:  BSF    08.1
....................       delay_cycles(1); 
032D:  NOP
....................       lcd.rw = 0; 
032E:  BCF    08.2
....................       delay_cycles(1); 
032F:  NOP
....................       lcd.enable = 0; 
0330:  BCF    08.0
....................       lcd_send_nibble(n >> 4); 
0331:  SWAPF  4C,W
0332:  MOVWF  4D
0333:  MOVLW  0F
0334:  ANDWF  4D,F
0335:  MOVF   4D,W
0336:  MOVWF  4E
0337:  CALL   2F8
....................       lcd_send_nibble(n & 0xf); 
0338:  MOVF   4C,W
0339:  ANDLW  0F
033A:  MOVWF  4D
033B:  MOVWF  4E
033C:  CALL   2F8
.................... } 
033D:  RETLW  00
....................  
....................  
.................... void lcd_init() { 
....................     BYTE i; 
....................     set_tris_lcd(LCD_WRITE); 
*
03E1:  MOVLW  00
03E2:  BSF    03.5
03E3:  MOVWF  08
....................     lcd.rs = 0; 
03E4:  BCF    03.5
03E5:  BCF    08.1
....................     lcd.rw = 0; 
03E6:  BCF    08.2
....................     lcd.enable = 0; 
03E7:  BCF    08.0
....................     delay_ms(15); 
03E8:  MOVLW  0F
03E9:  MOVWF  47
03EA:  CALL   2E3
....................     for(i=1;i<=3;++i) { 
03EB:  MOVLW  01
03EC:  MOVWF  3E
03ED:  MOVF   3E,W
03EE:  SUBLW  03
03EF:  BTFSS  03.0
03F0:  GOTO   3F9
....................        lcd_send_nibble(3); 
03F1:  MOVLW  03
03F2:  MOVWF  4E
03F3:  CALL   2F8
....................        delay_ms(5); 
03F4:  MOVLW  05
03F5:  MOVWF  47
03F6:  CALL   2E3
....................     } 
03F7:  INCF   3E,F
03F8:  GOTO   3ED
....................     lcd_send_nibble(2); 
03F9:  MOVLW  02
03FA:  MOVWF  4E
03FB:  CALL   2F8
....................     for(i=0;i<=3;++i) 
03FC:  CLRF   3E
03FD:  MOVF   3E,W
03FE:  SUBLW  03
03FF:  BTFSS  03.0
0400:  GOTO   40A
....................        lcd_send_byte(0,LCD_INIT_STRING[i]); 
0401:  MOVF   3E,W
0402:  CALL   045
0403:  MOVWF  3F
0404:  CLRF   4B
0405:  MOVF   3F,W
0406:  MOVWF  4C
0407:  CALL   304
0408:  INCF   3E,F
0409:  GOTO   3FD
.................... } 
....................  
....................  
.................... void lcd_gotoxy( BYTE x, BYTE y) { 
....................    BYTE address; 
....................  
....................    if(y!=1) 
*
033E:  DECFSZ 48,W
033F:  GOTO   341
0340:  GOTO   344
....................      address=lcd_line_two; 
0341:  MOVLW  40
0342:  MOVWF  49
....................    else 
0343:  GOTO   345
....................      address=0; 
0344:  CLRF   49
....................    address+=x-1; 
0345:  MOVLW  01
0346:  SUBWF  47,W
0347:  ADDWF  49,F
....................    lcd_send_byte(0,0x80|address); 
0348:  MOVF   49,W
0349:  IORLW  80
034A:  MOVWF  4A
034B:  CLRF   4B
034C:  MOVF   4A,W
034D:  MOVWF  4C
034E:  CALL   304
.................... } 
034F:  RETLW  00
....................  
.................... void lcd_putc( char c) { 
....................    switch (c) { 
0350:  MOVF   46,W
0351:  XORLW  0C
0352:  BTFSC  03.2
0353:  GOTO   364
0354:  XORLW  06
0355:  BTFSC  03.2
0356:  GOTO   36C
0357:  XORLW  02
0358:  BTFSC  03.2
0359:  GOTO   372
035A:  XORLW  01
035B:  BTFSC  03.2
035C:  GOTO   377
035D:  XORLW  04
035E:  BTFSC  03.2
035F:  GOTO   37C
0360:  XORLW  0A
0361:  BTFSC  03.2
0362:  GOTO   381
0363:  GOTO   386
....................      case '\f'   : lcd_send_byte(0,1);				 //Borrado del LCD 
0364:  CLRF   4B
0365:  MOVLW  01
0366:  MOVWF  4C
0367:  CALL   304
....................                    delay_ms(2); 
0368:  MOVLW  02
0369:  MOVWF  47
036A:  CALL   2E3
....................                                            break; 
036B:  GOTO   38C
....................      case '\n'   : lcd_gotoxy(1,2);        break;//Segundo renglon 
036C:  MOVLW  01
036D:  MOVWF  47
036E:  MOVLW  02
036F:  MOVWF  48
0370:  CALL   33E
0371:  GOTO   38C
....................      case '\b'   : lcd_send_byte(0,0x10);  break;//Backspace 
0372:  CLRF   4B
0373:  MOVLW  10
0374:  MOVWF  4C
0375:  CALL   304
0376:  GOTO   38C
....................      case '\t'	  : lcd_send_byte(0,0x0F);  break;//encendido del cursor 
0377:  CLRF   4B
0378:  MOVLW  0F
0379:  MOVWF  4C
037A:  CALL   304
037B:  GOTO   38C
....................      case '\r'	  : lcd_send_byte(0,0x0C);	 break;//Cursor apagado 
037C:  CLRF   4B
037D:  MOVLW  0C
037E:  MOVWF  4C
037F:  CALL   304
0380:  GOTO   38C
....................      case '\a'	  : lcd_send_byte(0,0x08);	 break;//LCD apagado 
0381:  CLRF   4B
0382:  MOVLW  08
0383:  MOVWF  4C
0384:  CALL   304
0385:  GOTO   38C
....................      default     : lcd_send_byte(1,c);     break; 
0386:  MOVLW  01
0387:  MOVWF  4B
0388:  MOVF   46,W
0389:  MOVWF  4C
038A:  CALL   304
038B:  GOTO   38C
....................    } 
.................... } 
038C:  RETLW  00
```


----------



## Leon Elec (Dic 15, 2008)

Fijate que chip tiene tu LCD. Dame el número del CI que está conectado a los pines de entrada. El otro CI es para el manejo de la pantalla y no nos sirve.


----------



## Leon Elec (Dic 15, 2008)

Perdón, ya se porque no te anda. Tu estás utilizando el 16F877, este PIC tiene entradas analógicas por el puerto A. Cuando se produce un reset, o lo que es lo mismo, cuando se inicializa, los pines del puerto A, están configuradas como entradas analógicas. Antes de inicializar al LCD, debes configurar el PORTA como salidas digitales.

Para ello, consulta el datasheet del PIC. Ahí hay un ejemplo de como configurarlo como salidas digitales.

Espero novedades.


----------



## jam0_0 (Dic 15, 2008)

Hola Leon, pues no tiene nombre el chip en el LCD porque esta en una pastilla o oblea, te adjunto los pdf's de los 2 lcd's que estoy usando. te adjunto los pdf's para que verifiques sale? en el programa que subí en mi primer post intenté usar la configuración que viene en el pdf, pues simulaba bien en el proteus pero ya sabes el triste final al implementarlo 

Saludos y gracias

ericklarva: gracias por tu programa que me has enviado, voy a intentar revisarlo.


----------



## jam0_0 (Dic 15, 2008)

Hola Leon pero porque es necesario configurar al puerto A como salidas digitales si no lo estoy usando? pues como sabrás estoy usando solo el puerto D

Estaré atento a tu respuesta


----------



## Leon Elec (Dic 15, 2008)

Perdón, me fie en el texto explicativo y no en las instrucciones  ops:  pero eso hiso darme cuenta de cual es el error. El error es que utilizas mal el mismo puerto para conectar todo el LCD. Para poder hacer esto, cuando envías datos al LCD por el puerto D, de la forma que está echa la rutina, modifica todo al puerto D incluyendo los pines conectados R/W, E, RS cuando no deberían ser afectados. Recuerda que esta rutina, fue creada para enviar datos por un puerto y controlar al LCD por otro.

Tienes dos opciones:



1- Modificar la rutina para que, cuando envíes los datos al LCD, no se afecten las 3 líneas R/W, E, RS

2- Cambiar estas 3 líneas a otro puerto.


----------



## jam0_0 (Dic 15, 2008)

Hola Leon, gracias por tu respuesta y tu apreciación, pues entonces parece que eso pasa, lo que te quería pedir de favor es que veas el primer programa que puse en el post, tambien lo simula bien el proteus y por lo que he visto al colocar en el proteus un voltimetro y haciendo los retardos extremos para que se vean pues la rutina no modifica esos 2 pines, digo 2 porque r/w está siempre a tierra si puedes ponerlo en ese diseño de proteus que he diseñado te podrás dar cuenta pues es ahí donde no se cual sea el error pues estoy casi seguro que ese codigo no modifica los pines e y rs.
Saludos


----------



## Leon Elec (Dic 16, 2008)

Yo no utilizo el proteus porque no es fiable en la simulación de PIC por ahora. Muchas cosas que ahí andaban, en la realidad no, y muchas cosas que ahí no andan, en la realidad si. Y por eso, no está más el proteus en mi PC.

Intenta hacer lo siguiente. Deja la librería como estaba (original) y respeta la conexión. Si anda, sabemos que tu LCD funciona bien. Si no anda, prueba con mi librería y también respeta la conexión. Si no anda, tenemos dos opciones:

1- El lcd roto

2- No es compatible con tu lcd.

Ahora no puedo simular paso por paso tu programa porque estoy trabado con el mío (ya hace dos días que estoy trabado)

Si logro salir de mi embrollo y confirmamos que tu LCD anda,  vemos como modificar a la librería para que funcione.


----------



## jam0_0 (Dic 16, 2008)

Ok, Leon, gracias por tu tiempo, voy a probar lo que me has dicho y te aviso.

Que programas me recomiendas para simular bien con pics así como el proteus?

Saludos


----------



## Leon Elec (Dic 16, 2008)

Yo pruebo mis programa con el MPLAB y si anda bien, lo monto en el protorboard y ahí me doy cuenta si metí la pata o no.


----------



## Ernesto (Jun 22, 2009)

Estimado Jamo_o:

Resolviste el problema?, la verdad es que tengo el mismo problema que tu, con la única diferencia que estoy programando en C, la verdad es que ya no se que hacer he cambiado todo de todo y no logro hacer que el LCD ande,(en PROTEUS funciona perfecto), pero en la realidad nada solo esa maldita linea negra.........., si encontraste el error por favor dime que es lo que hay que hacer.
Gracias de Antemano


----------



## gtacmilan (Jun 22, 2009)

como dice leon elec lo mejor para manejar una lcd con 16f877 es utilizar un puerto completo para los datos de la lcd y otros 3 pines de otros puertos para el E, RW y RS. puedes utilizar para estos 3 el Port E.


----------



## Chico3001 (Jun 22, 2009)

Muchas veces la linea negra se debe a error en la inicializacion.... verifiquen que la rutina de inicializacion del display sea adecuada y tenga los tiempos minimos requeridos...


----------



## maianus (Dic 11, 2009)

Hola jam0_0, tengo el mismo problema que vos y no se que mas probar. Yo programe en CCS. En proteus todo perfecto pero cuando paso a la realidad no pasa nada. La primera Linea del LCD se queda negra y no hay manera de hacerla andar. Si solucionaste y lo puedes publicar estaria agradecido


----------



## zera_milo (Dic 11, 2009)

Hola que tal..

Ps si su simulacion anda en proteus el diseño y la programacion deben estar bien, yo siempre simulo mis circuitos alli y e la realidad andan como debe de ser.

Espero y esten conectando a su LCD el potenciometro de contraste. Este potenciometro debe ser de 10 a 20K y se conecta al pin VEE (VO) de la LCD.
no esta demas agregar una resistencia de 4.7K a RS y a voltaje. Formando un divisor.

Cito estas sugerencias ya que por lo general se nos pasan por alto estos detalles..


Saludos...




Perdon no habia visto la primera pagina del post. Asi que el problema puede ser por los retardos en el envio de la informacion a la LCD, me paso varias veces.
Y es mas fiable si utilizas un puerto para el envio de informacion y otro para el control de la LCD, es decir los pines RW, RS, E. deberias probar con este diagrama. a mi me funciona.


----------



## solisbel (Feb 13, 2010)

Hola Jamo o.
Yo estoy haciendo un proyectico y tengo el mismo problema que tu. yo hice el programa en pic c, lo simule en proteus todo perfecto cuando lo monto en la realidad una linea negra en la lcd y no he podido desaparecer. No hace mas nada. Si tienes la solucion te lo agradesco ya no encuentro que hacer.. 
Es para el montaje de mi tesis. me quedan 4 dias.
Saludos


----------



## 1000tonto (Mar 29, 2010)

hola al fin pude ingresar de nuevo a mi perfil bueno lo voy a hacer simple por lo general los pic's de gama alta necesitan estabilizar su voltaje y si no lo hacen se paran reseteando esto en los pic's de la gama alta 18, para los 16f tb se debe cumplir lo mismo el problema que tienes es por que el lcd no se inicializa tal vez para probar lo que te digo direcciona un pin de otro puerto y enciende y apaga un led cierto tiempo, si esto sucede el problema esta en la circuiteria entre el lcd y el pic, espero comentarios, lo que el proteus es obiar algunas conexiones logicas como vcc y vss, nos vemos bye.

osea el proteus obia algunas conexiones, como la alimentacion de los integrados,etc.


----------

