problema con interrupciones pic 12f675

Hola buenas a tod@s

Soy aficionado a la electrónica y he dado con vuestro foro en varias ocasiones al hacer búsquedas en google. Me he decidido a escribir por que siempre me surge un problema a la hora de hacer algún “inventillo” utilizando pics.

El problema es que cuando utilizo interrupciones, estas son Hipersensibles, es decir con solo tocar la patilla de entrada con el dedo o la punta del tester el PIC detecta entrada y salta a la interrupción.

En mi ultimo diseño he utilizado un PIC 12f675 configurando gp1 como entrada (interrupción por cambio de estado de la patilla-GPIE) y gp2 también como interrupción (INTE). Mi idea es que cuando se detecta un nivel alto en GPI active la salida GP4 durante un determinado tiempo, y cuando se detecte un nivel alto en GP2 se active la salida GP5 el mismo intervalo de tiempo, así mismo si alguna salida está activa y se detecta nivel alto en la otra entrada se activaría la salida correspondiente.




Como digo he probado de todas maneras posibles, colocando resistencias de pull-up externas a masa y a VCC, resistencias de 200ohm, 1k, 10k. También he probado activando las resistencias de pull-up internas del PIC y nada. Tengo colocado un condensador de 100nf entre vcc y gnd. Ahora mismo lo tengo montado en una protoboard pero en circuito integrado pasa lo mismo.

A ver si tenéis idea donde estoy metiendo la pata. Esto también me ha pasado con pics 16f84 por lo que deduzco que es algún detalle que se me escapa a la hora de manejar pics.

Un saludo.

El codigo es el siguiente:


Código:
LIST P=16F675                ;utilizamos el pic 16f84
    
    include "P12F675.inc"     ;se incluye la definicion de los registros internos de una libreria

   
TEMPO EQU 0X21               ;valor de temporizador


    
    ORG 0                     ;inicio en el vector de reset   
    GOTO INICIO               ;va a la primera instruccion del programa
    ORG 4
    GOTO INTERRUPCION
    ORG 5                     ;salva vector de interrupcion



;comienzo del programa principal

INICIO
      
       BSF STATUS,RP0      ;entra en el  banco0
       MOVLW B'01000111'   
       MOVWF OPTION_REG    ;CONFIGURO TMR0 CON PREESCALADO 256, resistencias de pull-up puerta activadas, flanco ascendente para GP2    
       MOVLW B'00000110'
       MOVWF TRISIO         ;GP1 Y GP2 ENTRADA, DEMAS SALIDA
       MOVLW B'00000110'
       MOVWF WPU            ;ACTIVO RESISTENCIAS PULL-UP PARA LAS ENTRADAS (GP1 Y GP2)
       MOVLW B'00000010'
       MOVWF IOC           ;CONFIGURO GP1 COMO INTERRUPCION
       CLRF ANSEL          ;DESACTIVO CONVERSOR AD PARA USAR ENTRADAS
       BCF STATUS,RP0      ;VUELVE AL BANCO 0
       MOVLW 0X7
       MOVWF CMCON       ;DESACTIVO EL COMPARADOR PARA USAR ENTRADAS
       CLRF GPIO          ; pongo a 0 todas las salidas del puerto b
       
       
       
CONFIGURACION
      MOVLW B'10011000'       ; INTERRUPCION POR CAMBIO EN GP1 Y GP2
      MOVWF INTCON

 SUEÑO
      GOTO SUEÑO


;RUTINA DE TEMPORIZACION

TEMPORIZACION
        
        BCF INTCON,T0IF
        MOVLW 0X3D
        MOVWF TMR0
        
RUTINA1 
        BTFSS INTCON,T0IF
        GOTO RUTINA1
        DECFSZ TEMPO
        GOTO TEMPORIZACION
        RETURN

 


INTERRUPCION
      CLRF GPIO             ;paro los relés
      BTFSS INTCON,1        ;MIRA SI intf=1 (INTERMITENTE izquierdo)
      goto DERECHO          ;INTERMITENTE DERECHO
      goto IZQUIERDO        ;INTERMITENTE IZQUIERDO
 


IZQUIERDO
     
      BSF GPIO,5                  ;ACTIVA RELE
      MOVLW B'10001000'           ;ACTIVO LAS INTERRUPCIONES POR SI HAY QUE GIRAR A DERECHA (INTE DESACTIVADO)
      MOVWF INTCON                ;TEMPORIZACIÓN DE 2.65 SEGUNDOS APROX, PARA 4 PARPADEOS
      MOVLW 0X45                   
      MOVWF TEMPO
      CALL TEMPORIZACION                   
      BCF GPIO,5                 ;PARO RELÉ
ESPERO 
      BTFSC GPIO,2               ;ESPERO HASTA QUE EL INTEMITENTE ESTÉ APAGADO
      GOTO ESPERO
      MOVLW 0XA                  ;ESPERO 0.5 SEGUNDOS PARA VER SI REALMENTE EL INTERMITENTE ESTÁ APAGADO.
      MOVWF TEMPO
      CALL TEMPORIZACION
      BTFSC GPIO,2
      GOTO ESPERO
      GOTO CONFIGURACION

DERECHO
      
      BSF GPIO,4                 ;ACTIVA RELE
      MOVLW B'10010000'          ;ACTIVO LAS LAS INTERRUPCIONES POR SI HAY QUE GIRAR A IZQ (RBIE DESACTIVADO)
      MOVWF INTCON
      MOVLW 0X45
      MOVWF TEMPO
      CALL TEMPORIZACION          ;TEMPORIZACION DE UNOS 3.5 SEGUNDOS  (4 PARPADEOS)
      BCF GPIO,4                 ;PARO RELÉ
ESPERO2 
      BTFSC GPIO,1              ;ESPERO HASTA QUE EL INTERMITENTE DERECHO SE APAGUE
      GOTO ESPERO2
      MOVLW 0XA
      MOVWF TEMPO                 ;PEQUEÑA TEMPORIZACIÓN PARA EVITAR QUE SE ACTIVE EL RELÉ AL DESCONECTAR INTEMITENTE
      CALL TEMPORIZACION
      BTFSC GPIO,1
      GOTO ESPERO2
      GOTO CONFIGURACION
  
  END
 
Última edición por un moderador:
Hola:

De un vistazo rápido te digo algunas cosas:

1ro: Cuando una interrupción esta en proceso no se puede ejecutar otra, es decir si se activa IZQUIERDO no sirve de nada que actives otra interrupción en es bloque de código porque no le va hacer caso hasta que termine el bloque de código que pertenece a IZQUIERDO; solo es una interrupción a la vez.

2do: Al parecer no comprendes bien como funcionan las interrupciones, te explico brevemente:
-> En los 12F y 16F cuando una interrupción se activa, salta al vector de interrupción que es la dirección 0x04 y el stack almacena la dirección de retorno; en 0x04 puedes escribir el código de interrupción o saltar con goto a donde pongas el bloque de código que pertenece a la interrupción.
-> Se puede poner lo que sea en el bloque de interrupción menos activar otra interrupción en el mismo bloque de código; no es que no se pueda escribir, lo digo porque no funciona así aunque actives otra interrupción no le va hacer caso hasta que termine la actual.
-> Para salir del bloque de interrupción es necesario desactivar los flag's que provocan la interrupción y la instrucción "RETFIE" que hace dos cosas; activa interrupciones globales "GIE = 1" y retorna al código principal, una dirección después de cuando se ejecuto la interrupción.
-> Como una pauta: No se debe dejar demasiado tiempo ejecutándose a una interrupción ya que por lo general es usado para operaciones rápidas para luego volver al bloque principal, por eso se recomienda hacer la mayor parte de programa en el bloque principal y dejar a las interrupciones para ejecuciones rápidas.

3ro: Te dejo un link para que veas básicamente como se maneja una interrupción.


4to: No te aturdo más te paso tu código de como debería ser el orden, lo pruebas y me dices como te fue ya que no lo he revisado por completo, y lees lo que he comentado en tu código todo lo que empieza con ######:

Código:
;#################################################################
; Se supone que esto es el programa principal o el bucle principal.
; Se recomienda poner aqui el código principal + temporizadores, etc
; y dejar a las interrupciones para trabajos rápidos.
SUEÑO
	GOTO SUEÑO


;RUTINA DE TEMPORIZACION;
TEMPORIZACION
	BCF 	INTCON,T0IF
	MOVLW 	0X3D
	MOVWF 	TMR0

RUTINA1 
	BTFSS 	INTCON,T0IF		; ### No sirve de nada ya que cuando una interrupción
							; esta activada y se produce, salta inmediatamente al
							; bloque de interrupción, dejando de lado a estas instrucciónes,
							; además se recomienda borrar el flag que produjo la interrupción
							; al final del mismo bloque.
	GOTO 	RUTINA1
	DECFSZ 	TEMPO
	GOTO 	TEMPORIZACION
	RETURN

;-------------------------------------------------------------------------------------
INTERRUPCION ; ####################### Bien esto si se permite.
	CLRF 	GPIO 			;paro los relés
	BTFSS 	INTCON,1 		;MIRA SI intf=1 (INTERMITENTE izquierdo)
	goto 	DERECHO 		;INTERMITENTE DERECHO
	goto 	IZQUIERDO 		;INTERMITENTE IZQUIERDO

IZQUIERDO
	BSF 	GPIO,5 			;ACTIVA RELE
	MOVLW 	B'10001000' 	;ACTIVO LAS INTERRUPCIONES POR SI HAY QUE GIRAR A DERECHA (INTE DESACTIVADO)
							; ############ Como dije antes, activar interrupciones en una interrupcion no
							; funciona.
	MOVWF 	INTCON 			;TEMPORIZACIÓN DE 2.65 SEGUNDOS APROX, PARA 4 PARPADEOS
	MOVLW 	0X45 
	MOVWF 	TEMPO
	CALL 	TEMPORIZACION 
	BCF 	GPIO,5 ;PARO RELÉ
ESPERO 
	BTFSC 	GPIO,2 ;ESPERO HASTA QUE EL INTEMITENTE ESTÉ APAGADO
							; ####### Se permite pero no se recomienta esperar por tiempos
							; largos cuando está dentro de una interrupción
	GOTO 	ESPERO
	MOVLW 	0XA ;ESPERO 0.5 SEGUNDOS PARA VER SI REALMENTE EL INTERMITENTE ESTÁ APAGADO.
	MOVWF 	TEMPO
	CALL 	TEMPORIZACION	; ####### Se permite pero no se recomienda.
	BTFSC 	GPIO,2
	GOTO 	ESPERO
	GOTO 	CONFIGURACION	; ####### Jamás se debe de salir de una interrupción con una intruccipon "GOTO"
							; eso es lo que te causa inestabilidad en tu programa, para eso se debe de 
							; borrar el flag que probocó la interrupción y sar al final la instrucción "RETFIE".
							; Para eso e cambiado tu código y "CONFIGURACION" esta al final de código...

DERECHO

	GOTO 	CONFIGURACION

CONFIGURACION
	MOVLW 	B'10011000' ; INTERRUPCION POR CAMBIO EN GP1 Y GP2
	MOVWF 	INTCON
        ; ###### Aqui debes de borrar los flag's que probocaron la interrupción
	retfie				; ##### Retorna al programa principal y activa interrupciones globales
END
 
Atrás
Arriba