No entiendo las interrupciones en Pic

Hola a todos.

Hasta ahora nunca había utilizado interrupciones en programas para Pic, y pues me veo en la necesidad de utilizar una; la del TMR0.

No es un problema de programación, porque entiendo bien como hacerlo. El problema es que el Pic no hace lo que se supone hace una interrupción.

Buscando en Internet, definen interrupción mas o menos asi: " Es un llamado a una subrutina iniciada por el propio Pic o un periférico que detiene el programa principal y atiende la interrupción".

Hago entonces un programa de prueba (programa principal), que consiste en encender un led cada 500ms y apagarlo por otros 500ms; en la interrupción un programa de desborde de TMR0, incrementado una variable y después de 200 cuentas enciendo o apago un segundo led.

Aquí viene lo extraño...

- Se supone que el programa principal se detiene y atiende la interrupción. Eso no ocurre, los 2 programas (principal e interrupción) parecen funcionar de forma paralela, sin interferir entre ellos.

¿Qué sucede entonces?, alguien por favor que me explique.

Dejo el programa de prueba.

Gracias.

Código:
\'****************************************************************
\'*  Name    : TMR0.BAS                                          *
\'*  Author  : Gerson A.                                         *
\'*  Notice  : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS] *
\'*          : All Rights Reserved                               *
\'*  Date    : 12/09/2015                                        *
\'*  Version : 1.0                                               *
\'*  Notes   :                                                   *
\'*          :                                                   *
\'****************************************************************
Device = 16F88 \' Pic a utilizar
Config HS_OSC,PWRTE_ON,WDT_OFF,BODEN_OFF,CP_OFF,LVP_OFF
XTAL = 10        \' valor del oscilador
ALL_DIGITAL = 1 
CMCON = 7
TRISA = %00000000 \'pines de entrada en puerto A
TRISB = %00000000 \'pines de salida en puerto B

;----------------------- opciones del compilador --------------------------
                                                                   
Declare  SHOW_SYSTEM_VARIABLES = OFF 
Declare  FSR_CONTEXT_SAVE = OFF  
Declare  REMINDERS = OFF    
Declare  WARNINGS = OFF    
                                                                   
;-------------------------- PUERTOS --------------------------
                                                                   
Declare  PORTB_PULLUPS = OFF   
                                                                   
;----------------------------- VARIABLES ------------------------------------
Dim TIME As Byte                                                                   
;-------------------------- ALIAS OPTION REG --------------------------------
                                                                   
Symbol PS0 = OPTION_REG.0     
Symbol PS1 = OPTION_REG.1      
Symbol PS2 = OPTION_REG.2      
Symbol PSA = OPTION_REG.3     
Symbol T0SE = OPTION_REG.4     
Symbol T0CS = OPTION_REG.5      
Symbol INTEDG = OPTION_REG.6   
Symbol NOT_RBPU = OPTION_REG.7 
                                                                   
;--------------------------ALIAS INTCON -----------------------------------
                                                                   
Symbol RBIF = INTCON.0 
Symbol INTF = INTCON.1 
Symbol T0IF = INTCON.2 
Symbol RBIE = INTCON.3 
Symbol INTE = INTCON.4
Symbol T0IE = INTCON.5
Symbol PEIE = INTCON.6 
Symbol GIE = INTCON.7
--------------------ALIAS PUERTOS---------------------------------- 
Symbol LED1 = PORTB.0
Symbol LED2 = PORTB.1                                                                   
;-------------------------------- REINICIO DE BITS Y VARIABLES ----------------------------
LED1 = 0
LED2 = 0
T0IF = 0 
TIME = 0                                                                  
;----------------- AJUSTES DEL TMR0----------------------
OPTION_REG = %10000111
TMR0 = 0 ; TMR0
T0IE = 1    ; desborde bandera
                                                                   
GIE = 1    ; interrupcion global
                                                                   
ON_INTERRUPT GoTo  Int
GoTo  Main
                                                                   
;---------------------- RUTINA INTERRUPCION ----------------------
                                                                   
Int:
Context SAVE
TIME = TIME + 1
If TIME = 200 Then
GoTo INTER
Else
T0IF = 0
Context Restore
EndIf

INTER:
If LED2 = 0 Then
High LED2
Else
Low LED2
EndIf
TIME = 0
T0IF = 0
Context Restore                                                                   
                                                                   
;------------------------PROGRAMA PRINCIPAL -----------------------
                                                                   
Main:
High LED1
DelayMS 500
Low LED1
DelayMS 500                                                                   
                                                                   
GoTo  Main  
                                                                   
End ...
 
Última edición por un moderador:
- Se supone que el programa principal se detiene y atiende la interrupción. Eso no ocurre, los 2 programas (principal e interrupción) parecen funcionar de forma paralela, sin interferir entre ellos.

¿Qué sucede entonces?, alguien por favor que me explique.

pues de eso se trata, que aparentemete no interfieran entre ellos, pero no es paralelo es casi paralelo, porque te falta descontar el tiempo de ejecucion del programa de interrupcion(suma de instrucciones en ensamblador).

cuando se interrupe el programa principal despues de ejecutar la rutina de interrupcion regresa exactamente donde se interrumpio.
 
Última edición:
pues de eso se trata, que aparentemete no interfieran entre ellos, pero no es paralelo es casi paralelo, porque te falta descontar el tiempo de ejecucion del programa de interrupcion(suma de instrucciones en ensamblador).

cuando se interrupe el programa principal despues de ejecutar la rutina de interrupcion regresa exactamente donde se interrumpio.

Pero en mi caso eso no sucede. En la interrupcion el led enciende por 5 segundos y se apaga por otros 5 segundos, sin afectar el programa principal en donde el led se apaga 500ms y se enciende por 500ms :confused:
 
me parece que el delayms "congela" el micro, por eso esta haciendolo bien, esta parando tanto la interupcion como el programa principal, intenta hacer el retardo de los 500mS con otro algoritmo. hay muchas maneras.
 
Última edición:
me parece que el delayms "congela" el micro, por eso esta haciendolo bien, esta parando tanto la interupcion como el programa principal, intenta hacer el retardo de los 500mS con otro algoritmo. hay muchas maneras.

Ahora le aumente un tiempo de 500ms al encendido y apagado del led en la interrupcion, y efectivamente el programa principal se detuvo. Es exactamente como lo explico Papirrin.(y)

Muchas Gracias Papirrin:aplauso:, creo que ahora si lo entiendo. :)
 
¿Cómo es eso posible? ¿Por qué razón un bucle de espera detiene una interrupción? Eso no ocurre en otros lenguajes.

Salvo que... la propia delayms utilice el propio TMR0 para hacer la espera...
 
En realidad no me he puesto a revisar el código que genera el delay en básic pero supongo que "desconecta" el oscilador o olgo así, y no no utiliza ningún timer... Yo generalmente no lo uso y los retardos los hago con una rutina en ensamblador. En un rato que tenga me voy a poner a analizar que código genera porque si es algo que me parece esta mal diseñado.
 
Activa el TMR1 y usarlo como interrupcion, si ya no pasa que detenga la interrupcion el delay entonces es lo que comenta JoaquinFerrero de que usa la instruccion delay el TMR0 para generar retardos.

Saludos!
 
que compilador usas? microbasic,proton o cual?



Y si pruebas asi:

Código:
Int:
Context SAVE
TIME = TIME + 1
If TIME >= 200 Then
 time=0
 If LED2 = 0 Then
  High LED2
 Else
  Low LED2
 EndIf
EndIf

T0IF = 0
TMR0 = 0 ; TMR0
Context Restore

hay algo raro en tu codigo con el context restore
 
Última edición:
que compilador usas? microbasic,proton o cual?



Y si pruebas asi:

Código:
Int:
Context SAVE
TIME = TIME + 1
If TIME >= 200 Then
 time=0
 If LED2 = 0 Then
  High LED2
 Else
  Low LED2
 EndIf
EndIf

T0IF = 0
TMR0 = 0 ; TMR0
Context Restore

hay algo raro en tu codigo con el context restore

Me refiero a que no sale de la interrupción después de agregar delayms 500 al encender y apagar el led2. Con el primer programa (el que publique aquí) funciona muy bien.

Utilizo Proton.
 
Atrás
Arriba