Problema con RB0 PIC16f877 control luminosidad

Hola a todos,

Cuando ejecuto el siguiente código, sin interrumpir por RB0, el programa principal funciona con total normalidad.

El código debe abrir y cerrar una persiana dependiendo de la luz exterior (comparador con LDR) y controlar la intensidad lumínica interior, segun divisor de tensión con LDR. Todo esto junto con un detector de paso por cero. Controlan 2 relés, así como el disparo del triac. La parte del código principal actúa sobre las persianas, y calcula el tiempo que debe estar encendida la lampara.

Pues bien, la parte de la persiana la hace correctamente si no se activa el RB0. pero en el momento que se activa RB0, ya no vuelve a cambiar de estado, pero tampoco me dispara el triac.

Alguien me puede echar una manita?

A continuación el código y adjunto el diseño.

Código:
	PROCESSOR 16F877	; define tipo de procesador
	__CONFIG	0x3731	; 4Mhz frecuencia de reloj, standard fuse 
	#include <p16F877.inc>	; Etiquetas de registro estandard

; Registra etiquetas EQU

STATUS	EQU	0x03
PORTA	EQU	0x05	; Registro de datos del puerto A
PORTB	EQU	0x06	; Registro de datos del puerto B
PORTC	EQU	0x07	; Registro de datos del puerto C
PORTD	EQU	0x08	; Registro de datos del puerto D
TRISA	EQU	0x85	; Direccion del registro puerto A
TRISB	EQU	0x86	; Direccion del registro puerto B
TRISC	EQU	0x87	; Direccion del registro puerto C
TRISD	EQU	0x88	; Direccion del registro puerto D
ADCON0	EQU	0x1F
ADCON1	EQU 0x9F	;
ADRESH	EQU	0x1E

TMR0	EQU	0x01	; Registro de tiempo hardware
INTCON	EQU	0x0B	; Registro de control de interrupcion
OPTREG	EQU	0x81	; Registro de opciones

st_pers	EQU	0x20	; Var para control del estado de la persiana
st_LigH	EQU	0x21	; Var para control del estado de la luz
comp1	EQU	0x22	; Var resultado comparador 1 
comp2	EQU	0x23	; Var resultado comparador 2
Lampara	EQU	0x24	; Luminosidad de la lampara 0=baja..127=maxima
result	EQU	0x25	; Var para almacenar resultado comparacion.
estado	EQU	0x26	; Var para estados d las var XXXX X pers sint sext
count1	EQU	0x27	; Var para el contador de delay
count2	EQU	0x28	; Var para el contador de delay
W_Temp	EQU	0x70	; Guardamos registro W durante interrupcion (0x70 para acceder desde cualquier banco)
St_Temp	EQU	0x71	; Guardamos registro STATUS durante interrupcion(0x71 para acceder desde cualquier banco)
ls_adc	EQU	0x29	; Guardamos el valor despues de la conversion AD
DEMORA	EQU	0x2A	; Valor de demora para enceder el TRIAC
PDel0	EQU	0x2B	; Variable para el calculo de 5segundos de retardo
PDel1	EQU	0x2C	; Variable para el calculo de 5segundos de retardo	
PDel2	EQU	0x2D	; Variable para el calculo de 5segundos de retardo
Contador EQU 0x2E	; Variable para el retardo de 20us
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	ORG 	000		; Comienzo de la memoria del programa
	NOP				; Para el modo ICD
	GOTO 	init	; Salta al programa principal
	ORG		04
	GOTO	INT


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Inicializacion del puertos ..................................................

init
	BCF	STATUS,7	; Configuro el bit FSR a 0 xa trabajar bank0/1
	BCF	STATUS,5	; Seleccion el bank0 de memoria	RP0
	BCF	STATUS,6	; poniendo 00 en RP0:RP1
	BCF	estado,2	; Inicia el estado de la persiana a cerrado
	BCF	estado,3	; Ha contado los 5 segundos de accion de persiana?
	CLRF	PORTA		; Limpia los puertos del A al D
	CLRF	PORTB
	CLRF	PORTC
	CLRF	PORTD
	BSF	STATUS,5	; Selecciono el bank 1 poniendo 01 RP0:RP1
	MOVLW	0X80		; 
	MOVWF	ADCON1		; Todos los pines del puerto A son analogicos
	MOVLW	0XCF		;
	MOVWF	TRISA		; Todos los pines del puerto A son entradas

	NOP			; BANKSEL no puede ser etiquetada
	BANKSEL	TRISB		; Selecciona el bank1
	MOVLW	b'11111101'	; Configura el RB1 como salida(b'11111101') 253
	MOVWF	TRISB		; Carga el codigo DDR en F86

	NOP			; BANKSEL no puede ser etiquetada
	BANKSEL	TRISC		; Selecciona el bank1
	MOVLW	b'01111111'	; Configura RC6 y RC7 como salida(b'01111111') 127
	MOVWF	TRISC		; Carga el codigo DDR en F87

	NOP			; BANKSEL no puede ser etiquetada
	BANKSEL	TRISD		; Selecciona el bank1
	MOVLW	b'00000000'	; Configura RD1 a RD4 como salida(b'11111100') 252
	MOVWF	TRISD		; Carga el codigo DDR en F88

	NOP			; BANKSEL no puede ser etiquetada
	BANKSEL	TRISE		; Selecciona el bank1
	MOVLW	b'00000000'	; Configura bit4 a 0 xa utilizar portd como puertos gnral
	MOVWF	TRISE		; 

 	
	MOVLW B'11000111'	;EL PRESCALER ES ASIGNADO AL TMR0 
	MOVWF OPTION_REG
	MOVLW B'10010000'	;INTERRUPCION POR PIN RB0
	MOVWF INTCON
	BANKSEL 0
	GOTO	Ppal
	

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

INT

	BTFSS INTCON, INTF
	GOTO OTROCASO
	BCF	INTCON, INTE
	MOVF DEMORA, W
	MOVWF TMR0
	BSF INTCON, INTE
	BCF	INTCON, T0IF

BACK
		RETFIE

OTROCASO
	BCF INTCON, INTE
	BSF PORTB,1
	BSF INTCON, INTE
	BCF INTCON, T0IF
	GOTO BACK



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Programa principal
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



Ppal
	CALL	Capdat	; Llamamos la subrutina de captura de datos
	CALL	nivluz1	; Llamamos la subrutina de tratamiento de datos para dimmer
	CALL	persia	; Ejecutamos la subrutina de actuacion de las persianas
	GOTO	Ppal

;Subrutina de captura de datos.................................................



; Adquisicion datos de la LDR para intensidad interior habitacion
; Inicializacion de la conversion AD. Reloj de conversion 4MHz/32,AN4 canal seleccionado como 
; AN0,AD conversion OFF,AD modulo de conversion encendido

Capdat	
		banksel ADCON0        
		movlw b'01000001'    ; fosc 8, RA0 analogico
		movwf ADCON0    

; Incializacion convertidor AD. Justificado a la izquierda, todos los PORTA como entrada analogica

 	banksel ADCON1
 	movlw b'00001110'	;Justificado a la izquierda, canal 0, modulo habilitado
 	movwf ADCON1
	call Demora_20us	; Esperamos el tiempo de adquisicion necesario
; Comenzamos la conversion AD

 	banksel ADCON0
 	bsf ADCON0,2

; Esperamos que acabe la conversion

espera
	btfsc ADCON0,2    
	goto espera

; Guardamos el valor despues de la conversion en la variable ls_adc.

	banksel ADRESH
	movf ADRESH,0       ; Despues de finalizar la conversion AD el valor en ADRESH se guarda en el Reg W 
						; y el valor en ADRESL se omite, esa precision no es necesaria.
	banksel ls_adc
	movwf ls_adc        ; valor en W Reg. se escribe en la variable ls_adc
	RETURN

Demora_20us
	movlw 0x05
	movwf Contador		; iniciamos contador
Repeticion
	decfsz Contador,1	; Decrementa Contador en 1
	goto Repeticion		; Si no es cero repetimos el ciclo
	RETURN

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Tratamiento de los datos, comparativa de niveles de luz.......................
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

nivluz1
	MOVLW 	b'01111111'	; cargo valor a comparar nivel con 2,5V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem10ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz2		; en caso de que sea menor comprobamos siguiente intervalo
dem10ms
	MOVLW	b'11011001'	; cargamos 217 en DEMORA que corresponde con 10ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz2
	MOVLW 	b'01110010'	; cargo valor a comparar nivel con 2.25V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem9ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz3		; en caso de que sea menor comprobamos siguiente intervalo
dem9ms
	MOVLW	b'11000011'	; cargamos 195 en DEMORA que corresponde con 9ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz3
	MOVLW 	b'01100110'	; cargo valor a comparar nivel con 2V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem8ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz4		; en caso de que sea menor comprobamos siguiente intervalo
dem8ms
	MOVLW	b'10101101'	; cargamos 173 en DEMORA que corresponde con 8ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz4
	MOVLW 	b'01011001'	; cargo valor a comparar nivel con 1.75V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem7ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz5		; en caso de que sea menor comprobamos siguiente intervalo
dem7ms
	MOVLW	b'10010111'	; cargamos 151 en DEMORA que corresponde con 7ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz5
	MOVLW 	b'01001100'	; cargo valor a comparar nivel con 1.5V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem6ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz6		; en caso de que sea menor comprobamos siguiente intervalo
dem6ms
	MOVLW	b'10000010'	; cargamos 130 en DEMORA que corresponde con 6ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz6
	MOVLW 	b'00111111'	; cargo valor a comparar nivel con 1.25V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem5ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz7		; en caso de que sea menor comprobamos siguiente intervalo
dem5ms
	MOVLW	b'01101100'	; cargamos 108 en DEMORA que corresponde con 5ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz7
	MOVLW 	b'00110011'	; cargo valor a comparar nivel con 1V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem4ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz8		; en caso de que sea menor comprobamos siguiente intervalo
dem4ms
	MOVLW	b'01010110'	; cargamos 86 en DEMORA que corresponde con 4ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz8
	MOVLW 	b'00100110'	; cargo valor a comparar nivel con 0.75V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem3ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	nivluz9		; en caso de que sea menor comprobamos siguiente intervalo
dem3ms
	MOVLW	b'01000001'	; cargamos 65 en DEMORA que corresponde con 3ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

nivluz9
	MOVLW 	b'00011001'	; cargo valor a comparar nivel con 0.5V
	SUBWF 	ls_adc,W	; comparamos ambos registros
	BTFSC	STATUS,Z	; Si son iguales se ejecuta la siguiente, en caso contrario se salta
	GOTO	dem2ms
	BTFSS	STATUS, C	; comprobamos el bit de complemento para saber si es mayor o menor
	GOTO	no_dem		; en caso de que sea menor no aplicamos ninguna demora
dem2ms
	MOVLW	b'00101011'	; cargamos 65 en DEMORA que corresponde con 2ms para el TMR0
	MOVWF	DEMORA		; ya que hay luz y no necesitamos que este encendida
	RETURN

no_dem
	MOVLW	b'00000000'	;no aplicamos ninguna demora, al estar en completa oscuridad
	MOVWF	DEMORA
	RETURN

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Tratamiento de los datos, accion de persiana..................................
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



persia
	BTFSC	estado,2	;testeo del bit persiana
	GOTO	abierta		; Si 1 voy a comprobar el bit de estado de la luz
	GOTO	cerrada		; Si 0 voy a comprobar el bit de estado de la luz
abierta
	BTFSS	PORTB, 4	; testeo si hay luz exterior
	GOTO	cerrar		; Si no hay luz, entonces cerramos la persiana
	RETURN			; Si hay luz, no hacemos nada
cerrada
	BTFSS	PORTB, 4	; testeo si hay luz exterior
	RETURN			; si no hay luz ext, no hacemos nada
	GOTO	abrir		; Si hay luz exterior, lo abrimos
abrir
	BSF 	PORTD,0		; mandamos un 1 por RD0 para abrir
	CALL 	espera5s	; Esperamos 5 segundos (tiempo a regular) para dejar terminar la apertura
	BCF		PORTD,0		; Apagamos la señal del puerto D0
	NOP
	BSF		estado,2	; Actualizamos la bandera del bit de estado a abierto
	RETURN
cerrar
	BSF		PORTD,1		; mandamos un 1 por RD1 para cerrar
	CALL	espera5s	; Esperamos 5 segundos (tiempo a regular) para dejar terminar la apertura
	BCF 	PORTD,1		; Apagamos la señal del puerto D1
	NOP
	BCF		estado,2	; Actualizamos la bandera del bit de estado a cerrado
	RETURN
;-------------------------------------------------------------
espera5s
		movlw     .165  	; 1 set numero de repeticion  (C)
        movwf     PDel0    	; 1 |
PLoop0
		movlw     .41      	; 1 set numero de repeticion  (B)
        movwf     PDel1    	; 1 |
PLoop1
		movlw     .147      	; 1 set numero de repeticion  (A)
        movwf     PDel2     	; 1 |
PLoop2
		clrwdt              	; 1 clear watchdog
        clrwdt              	; 1 ciclo delay
        decfsz    PDel2, 1  	; 1 + (1) es el tiempo 0  ? (A)
        goto      PLoop2    	; 2 no, loop
        decfsz    PDel1,  1 	; 1 + (1) es el tiempo 0  ? (B)
        goto      PLoop1    	; 2 no, loop
        decfsz    PDel0,  1 	; 1 + (1) es el tiempo 0  ? (C)
        goto      PLoop0    	; 2 no, loop
        return              	; 2+2 Fin.
;-------------------------------------------------------------

	END
 
Pues así, a simple vista veo alguna cosilla. No sé si el problema estará ahí, pero:

Primero, parece que asumes que si la interrupción no es generada al paso por cero, el único OTROCASO es que se haya terminado el tiempo de espera del timer.

Segundo, mirando el datasheet del PIC que estás utilizando, observo que cuando se genera una interrupción se guarda la dirección de retorno en el STACK... y nada más. Por tanto, deberías salvar el valor de los registros (mira el W) y no lo haces.

Hasta luego.
 
Atrás
Arriba