Problemas Código Termometro PIC16F887

Buenas a todos.

Estoy realizando un proyecto con el PIC16887, que trata de visualizar la temperatura en la pantalla LCD, mediante un LM35.

No se que estoy haciendo mal en el codigo que siempre me da una temperatura de 55 grados Celsius, espero que me podais ayudar.

Os adjunto el codigo del programa principal y las rutinas de visualizacion en pantalla y conversor AD


Código:
;**********************************************************************************
; Programa principal
;**********************************************************************************


INICIALIZACIONES:
;****** Inicializaciones
		CALL	INITPORTS
		CALL	INITTEC
		CALL	INITLCD
	;*	CALL	INIC_REL		; Inicializar RELOJ
		CALL    INITSER
		CALL	INITAD			; Inicializa el conversor analogica/Digital
		BSF 	STATUS,RP0 		; Banco 1
		MOVLW	d'125'			;
		MOVWF	CONT			;
; Inicialización timer 0 (frecuencia cristal = 4 MHz)
		MOVLW	B'000000011' 	; Fosc/4= 1000000, Fpreescaler (64)--> mueve ese vaor al acumulador
		MOVWF 	OPTION_REG&7F 	; Preescaler = 64
		BCF 	STATUS,RP0 		; Banco 0 --> pone a 0 el bit RP0 de STATUS
		BCF 	P_LED,b_LED 	; pone a 0 el bit b_led de P_led --> enciende el led
		CALL	INICTEMP		;
		MOVLW	0				;
		MOVWF	estado			;
		MOVLW	d'3'			;
		MOVWF	BCDA2			;
		MOVLW	d'0'			;
		MOVWF	BCDA1			;
		CLRF	TEMPAL			;
; Inicialización interrupciones
		MOVLW 	B'10100000' 	; habilita las interrupciones causadas por el TMR0
		MOVWF 	INTCON 			; Interrupción de TMR0 habilitada



;****** Lazo principal
LAZOPPAL:
		CALL	CONVERSOR		; Llama a la rutina de conversion
		CALL 	VISUALIZARTEMP
		CALL    PASARPC
		CALL	ESPERA500
		CALL 	LIMPIAPANT
		CALL 	ESPERA500
		GOTO 	LAZOPPAL 		; Se cierra lazo principal



;****************************************************
;VISUALIZACION***************************************
;****************************************************




VISUALIZARTEMP:
	MOVLW	segunda		; 
	CALL	LCDIWR		; Colocar el cursor en la 1era posicion de la segunda linea
	MOVLW	A'T'		;
	CALL	LCDDWR		;		T
	MOVLW	A'-'		;
	CALL	LCDDWR		;		-
	MOVLW	A'>'		;
	CALL	LCDDWR		;		>
	MOVLW	A' '		;
	CALL	LCDDWR		;	
	MOVF	BCD1,W	;
	CALL	LCDNWR		;		x
	MOVF	BCD0,W	;		
	CALL	LCDNWR		;		x		 
	MOVLW	A'C'		;
	CALL	LCDDWR		;		C
	MOVLW	A' '		;
	CALL	LCDDWR		;
	MOVLW	A' '		;
	CALL	LCDDWR		;

	RETURN				;



LIMPIAPANT:
	MOVLW	lcd_clr		;
	CALL	LCDIWR		; Limpiar pantalla
	;BSF		flags,flimp	;
	RETURN				;
;****************************************************
;Conversor AD****************************************
;****************************************************
INICTEMP:
	MOVLW	d'0'			;
	MOVWF	BCD0			;
	MOVLW	d'0'			;
	MOVWF	BCD1			;
	RETURN					;

INITAD:
	BSF		STATUS,RP0		; Banco 1
	MOVLW		B'00000101'		; Configura conversor AD (primera parte)
	MOVWF		ADCON1&7F		; RA3: Vref+, RA1 y RA0: entradas analogicas, justificadpo a la derecha
	BSF		TRISA&7F,0		; Se configuran como entradas las entradas analogicas del puerto A
	BSF		TRISA&7F,1		; 
	BSF		TRISA&7F,3		; 
	BCF		STATUS,RP0		; Banco 0
	BCF		ADCON0,ADCS1	; Configura conversor AD (segunda parte)
	BSF		ADCON0,ADCS0	; Velocidad de conversion Tosc/8 (Maximo para 4MHz)
	BCF		ADCON0,CHS2		; Canal 0
	BCF		ADCON0,CHS1		;
	BCF		ADCON0,CHS0		;
	BSF		ADCON0,ADON		; Conversor encendido
	RETURN					;

CAN0:		; Fija el canal 0 para la conversion AD
	BCF		ADCON0,CHS2		; Canal 0
	BCF		ADCON0,CHS1		;
	BCF		ADCON0,CHS0		;
	RETURN					;

CAN1:		; Fija el canal 0 para la conversion AD
	BCF		ADCON0,CHS2		; Canal 1
	BCF		ADCON0,CHS1		;
	BSF		ADCON0,CHS0		;
	RETURN					;

CONVAD:
	BSF		ADCON0,GO		; Se inicia la conversion
	RETURN					;

CONVAD1:
	MOVF	ADRESH,W		; Se toma el valor del conversor y se guarda en variables de salida
	MOVWF	CAD1			;
	MOVWF	CAD2			;
	CALL	INICTEMP		; Limpiamos las variables
	GOTO	BIN2BCD			;
					
CONVERSOR:
	BTFSC	ADCON0,GO		; Comprueba el valor de GO/DONE
	RETURN					;
	CALL	CONVAD1			;
	CALL	CONVAD			;
	RETURN					;

BIN2BCD:
	DECF	CAD1			; Copia la variable T al entorno de trabajo
	BTFSC	STATUS,Z		; Comprueba si el bit Z de STATUS es 0
	RETURN					;
	CALL	INCRBCD			; Va a la funcion INCRBCD
	GOTO	BIN2BCD			; Va a la funcion BIN2BCD
	
INCRBCD:
	INCF	BCD0			; Incrementamos BCD0
	BTFSC	BCD0,u0			; Comprobar si el LSB es 0
	RETURN					;
	BTFSS	BCD0,u1			; comprobar si el segundo desde atras es 1
	RETURN					;
	BTFSC	BCD0,u2			; Comprobar si el tercero desde atras es 0
	RETURN					;
	BTFSS	BCD0,u3			; Comprobar si el cuarto desde atras es 1
	RETURN					;
	CLRF	BCD0			; Limpia el registro BCD0
	INCF	BCD1			; Incrementa BCD1
	BTFSC	BCD1,u0			; Comprobar si el LSB es 0
	RETURN					;
	BTFSS	BCD1,u1			; comprobar si el segundo desde atras es 1
	RETURN					;
	BTFSC	BCD1,u2			; Comprobar si el tercero desde atras es 0
	RETURN					;
	BTFSS	BCD1,u3			; Comprobar si el cuarto desde atras es 1
	RETURN					;
	CLRF	BCD1			; Limpia el registro BCD1
	RETURN					;


	RETURN					;
 
Última edición por un moderador:
Si no incluyes el código completo y algún esquema, es muy difícil encontrar el problema.
Sin embargo, veo algo mal en tus rutinas, por ejemplo, en la rutina CONVERSOR
Tienes esto:
BTFSC ADCON0,GO
RETURN

Aquí compruebas el estado del bit GO/DONE, pero retornas si está en 1 (Conversión en progreso.)
Eso no es correcto, pues retornarás al lugar de la llamada y no obtendrás la lectura del registro ADRESH.
Debes esperar a que se complete la conversión (ADCON0,1 = 0) pero sin retornar hasta que tomes la lectura.

Puedes hacerlo así:
Código:
    btfsc    ADCON0,GO
    goto    $-1
    movf    ADRESH,W
    ; etc.
    return
O así:
Código:
espero_adc
    btfsc    ADCON0,GO
    goto    espero_adc
    movf    ADRESH,W
    ; etc.
    return
Y esto que te menciono lo tienes en varias partes del programa.
Me parece que puedes simplificar las rutinas en una sola estructura para no crear varias, pues así como tienes el programa, es un ir y venir entre rutinas que puedes reducir.
 
Última edición:
Muchas gracias!!

Ahora me he centrado en el conversor únicamente, ya que creo que es lo que está mal.
Hemos medido sin poner el LM35 y nos sigue midiendo 55\, por lo que no está convirtiendo nada.

A ver que os parece la vuelta que le he dado a las rutinas para que me convierta y me pase a BCD

Código:
;****** Lazo principal
LAZOPPAL:
        CALL    CONVAD        ; Llama a la rutina de conversion
        CALL     VISUALIZARTEMP
        CALL   PASARPC
        CALL    ESPERA500
        CALL     LIMPIAPANT
        CALL     ESPERA500
        GOTO     LAZOPPAL         ; Se cierra lazo principal

;****************************************************
;Conversor AD****************************************
;****************************************************
INICTEMP:
    MOVLW    d'0'            ;
    MOVWF    BCD0            ;
    MOVLW    d'0'            ;
    MOVWF    BCD1            ;
    RETURN                    ;

;**********************************************************************************
; INITAD
; Inicializa conversor AD

INITAD:
    BSF    STATUS,RP0    ; Banco 1: Configura conversor AD (parte I):
    MOVLW    B'10010101'    ;    Vref+ en RA3
                ;    justificado a la derecha
                ;  y sólo para PIC16F87x:
                ;    RA1 y RA0 son entradas analógicas,
    MOVWF    ADCON1&7F    ;
    BSF    TRISA&7F,0    ; Se configuran RA0,RA1 y RA3 como 
    BSF    TRISA&7F,1    ; entradas del puerto A
    BSF    TRISA&7F,3    ;

                ; 
    BSF     STATUS,RP0     ; Banco 3: Configura conversor AD (parte II):
    BSF     STATUS,RP1     ; 
    BSF    ANSEL&7F,ANS0     ; Sólo para PIC16F88x: RA0 entrada analógica
    BSF    ANSEL&7F,ANS1     ; Sólo para PIC16F88x: RA1 entrada analógica
    BCF     STATUS,RP0     ; 
    BCF     STATUS,RP1     ;

    BCF    STATUS,RP0    ; Banco 0: Configura conversor AD (parte III):
    BCF    ADCON0,ADCS1    ;  velocidad de conversión Tosc/8 (máx. para 4MHz)
    BSF    ADCON0,ADCS0    ;
    BCF    ADCON0,CHS0    ;  canal 0
    BCF    ADCON0,CHS1    ;  
    BCF    ADCON0,CHS2    ;    
    BCF    ADCON0,CHS3    ;   (Sólo para PIC16F88x)      
    BSF    ADCON0,ADON    ;  conversor encendido        
        
    RETURN                    


;**********************************************************************************
; CAN0
; Fija el canal 0 para la conversión AD
    BCF    ADCON0,CHS0    ;  canal 0
    BCF    ADCON0,CHS1        
    BCF    ADCON0,CHS2
    BCF    ADCON0,CHS3    ;   (Sólo para PIC16F88x)      
    RETURN


;**********************************************************************************
; CAN1
; Fija el canal 1 para la conversión AD
    BSF    ADCON0,CHS0    ;  canal 1
    BCF    ADCON0,CHS1        
    BCF    ADCON0,CHS2
    BCF    ADCON0,CHS3    ;   (Sólo para PIC16F88x)      
    RETURN


;**********************************************************************************
; CONVAD
; Conversión AD

CONVAD:
    BSF    ADCON0,GO        ; Se inicia conversión
CONVAD1:
    BTFSC    ADCON0,GO        ; Se espera a que concluya conversión
    GOTO    CONVAD1

    MOVF    ADRESH,W            ; Se toma el valor del conversor y se
    MOVWF    CAD1            ; guarda en variables de salida
    BSF    STATUS,RP0
    MOVF    ADRESL&7F,W
    BCF    STATUS,RP0
    MOVWF    CAD0            ; guarda en variables de salida
    CALL    INICTEMP        ; Limpiamos las variables
    GOTO    BIN2BCD            ;
    RETURN


BIN2BCD:
    DECF    CAD1            ; Copia la variable T al entorno de trabajo
    BTFSC    STATUS,Z        ; Comprueba si el bit Z de STATUS es 0
    RETURN                    ;
    CALL    INCRBCD            ; Va a la funcion INCRBCD
    GOTO    BIN2BCD            ; Va a la funcion BIN2BCD
    
INCRBCD:
    INCF    BCD0            ; Incrementamos BCD0
    BTFSC    BCD0,u0            ; Comprobar si el LSB es 0
    RETURN                    ;
    BTFSS    BCD0,u1            ; comprobar si el segundo desde atras es 1
    RETURN                    ;
    BTFSC    BCD0,u2            ; Comprobar si el tercero desde atras es 0
    RETURN                    ;
    BTFSS    BCD0,u3            ; Comprobar si el cuarto desde atras es 1
    RETURN                    ;
    CLRF    BCD0            ; Limpia el registro BCD0
    INCF    BCD1            ; Incrementa BCD1
    BTFSC    BCD1,u0            ; Comprobar si el LSB es 0
    RETURN                    ;
    BTFSS    BCD1,u1            ; comprobar si el segundo desde atras es 1
    RETURN                    ;
    BTFSC    BCD1,u2            ; Comprobar si el tercero desde atras es 0
    RETURN                    ;
    BTFSS    BCD1,u3            ; Comprobar si el cuarto desde atras es 1
    RETURN                    ;
    CLRF    BCD1            ; Limpia el registro BCD1
    RETURN                    ;


    RETURN
 
Última edición por un moderador:
Pues a simple vista parece que la rutina del conversor ya está más o menos bien, pero sigo viendo retornos sin sentido.
Por ejemplo, los que siguen a continuación de GOTO BIN2BCD y en la rutina INCRBCD

Sería mejor que adjuntaras el proyecto completo dentro de un archivo comprimido.
 
Aqui va comprimido

Muchas gracias por la ayuda, en serio. Tengo que entregar para dentro de dos semanas el proyecto y me estoy volviendo loco. Y esto solo es el inicio, se supone que tengo que enviar al PIC una temperatura concreta y mediante un ventilador y una bombilla controlados por el PIC tiene que medir esa temperatura el sensor. :cry:
 

Adjuntos

  • Term.rar
    37.6 KB · Visitas: 4
Muchas gracias por la ayuda, en serio. Tengo que entregar para dentro de dos semanas el proyecto y me estoy volviendo loco. Y esto sólo es el inicio, se supone que tengo que enviar al PIC una temperatura concreta y mediante un ventilador y una bombilla controlados por el PIC tiene que medir esa temperatura el sensor. :cry:
OK, mejor adjunto un ejemplo usando el ADC para que tengas una idea, porque si hay mucho que modificar en tu programa.
Con este ejemplo adaptado a tu programa, ya podrás al menos tener la certeza del funcionamiento del conversor.

Como tienes que realizar varias rutinas en tu programa, te recomiendo que realices programas de prueba independientes para que compruebes su funcionamiento, posteriormente cuando los tengas funcionando, los incluyes al programa final.

También puedes crear tus rutinas en archivos *.inc, que después podrás usar como librerías.
Así te evitarás estar buscando errores, mejorarás los bloques del programa y lo harás más rápido.
 

Adjuntos

  • 16F887 ADC 10 bits.rar
    23.8 KB · Visitas: 14
Ya consegui medir la temperatura!!!!!!!

El mayo problema lo tenia en el circuito que me da la Tension de referencia, mucha graciasp or las ayudas.

Lo que no me ha quedado claro es como saber el numero binario que te va a salir de la conversion con un tension de entrada determinada.
 
Lo que no me ha quedado claro, es cómo saber el número binario que te va a salir de la conversión con una tensión de entrada determinada.
Pues eso depende de la fórmula de conversión que realices.
Si realizas la conversión directa obteniendo el resultado de los 10 Bits, tendrás un valor de 0 a 1023.
0 V = b'0000000000'
5 V = b'1111111111'
Entonces: 5V / 1023 = 0.00488V.
O sea que cada 4.88mV. Aproximadamente, se irá incrementando una unidad. (1023 pasos de 4.88mV.)

Ahora por ejemplo:
En el caso de un sensor LM35 a 150 °C, se supone que tendremos 1.5V. en su salida y el valor del ADC estará en 308 aproximadamente.
Entonces: 308 * 4.88mV = 1.50304V.
Y ahora para obtener el valor del ADC: 1.50304V / 0.00488V = 308
 
Última edición:
Atrás
Arriba