Autor Tema: on interrupt  (Leído 2685 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Picoffon

  • PIC10
  • *
  • Mensajes: 19
on interrupt
« en: 24 de Noviembre de 2004, 11:44:00 »
¿Alguien me sabría explicar claramente como funcionan las interrupciones por hardware con la instrucción "on interrupt goto etiqueta"?

Es que me gustaría interrumpir mi programa en el caso de que reciba un 1 por el pin porta.0 de mi pic 16f84a. Esto debe ocurrir solo dentro de una parte de mi programa, y en esa parte debo hacer una pausa de un tiempo en concreto. Más o menos, se que tengo que modificar el valor del registro INTCON,  pero no se que valor hay que darle para que haga lo que quiero. Por otra parte no se si funcionará de manera similar al gosub, es decir, en el caso de que ocurra un evento, se va a una etiqueta, y después vuelve al lugar de programa donde estaba o al lugar donde le diga.
Otra cosa, ¿puede interrumpirse en mitad de una pausa?, es decir, mientras está en (por ejemplo) pause 30000.

Gracias a todos, espero que alguno tenga la paciencia de contestarme, porque cuando uno está empezando con todo esto, le surgen muchas dudas.Sonrisa

Desconectado RGL

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 634
RE: on interrupt
« Respuesta #1 en: 24 de Noviembre de 2004, 12:08:00 »
Te pongo un ejemplo que no es la interupción por B0, pero puede ser gráfico para que lo aprendas.

Es un led que se apaga y enciende y luego una interrupción por B4 (cambio de estado en el nible alto del port B).





"***************************************
"*          FUSIBLES                   *
"***************************************

CONFIG HS_OSC , WDT_OFF , PWRTE_ON , BODEN_ON , LVP_OFF , WRT_HALF , CPD_ON , DEBUG_OFF

   " Oscilador en alta frecuencia (20MHz)   
   " Watchdog Timer desconectado
   " Power-On Timer conectado
   " Brown-Out Detect conectado
   " Low Voltage Programming desconectado
   " Data Memory Code Protect la mitd
   " Flash Program Memory Protect activado
    " In Circuit Debuger desactivado    
   " Program Code Protection activado
   
"** FIN DE FUSIBLES

"*****************************
"*        DEFINE             *
"*****************************

 DEVICE 16F877A
 
 ON_INTERRUPT INT_tecla           "Interrupcion hardware si se pulsa una tecla
 
 DECLARE XTAL 20                  "Frecuencia del reloj 20MHz
 DECLARE WATCHDOG OFF             "Wachdog desconectado
 DECLARE BOOTLOADER ON            "Bootloader conectado
 DECLARE HBUS_BITRATE 100         "Reloj bus I2C a 100KHz
" DECLARE HSERIAL_BAUD 9600        " Velocidad puerta serie a 9600
" DECLARE HSERIAL_RCSTA %10010000  " Recepcion del puerto serie continua
" DECLARE HSERIAL_TXSTA %00100000  " Transmision modo asincrono habilitada
" DECLARE HSERIAL_CLEAR ON         " Limpieza bufer antes de la recepcion

DECLARE RSOUT_PIN PORTC.6
DECLARE RSOUT_MODE TRUE
DECLARE SERIAL_BAUD 9600
DECLARE RSOUT_PACE 100
 
" DECLARE LCD_TYPE 0          "LCD tipo alfanumerico
" DECLARE LCD_DTPIN PORTD.0   "Data pin en puerto D con 8 bits
" DECLARE LCD_ENPIN PORTA.0   "bit Enable en  puerto A bit 0
" DECLARE LCD_RSPIN PORTA.2   "Linea RS esta en puerto A bit 2
" DECLARE LCD_INTERFACE 8     "Bus de datos de 8 bit
" DECLARE LCD_LINES 2         "Display de dos lineas
 
" DECLARE SDA_PIN PORTC.4
" DECLARE SCL_PIN PORTC.3
" DECLARE SLOW_BUS ON


"** FIN DE DEFINE


"DEFINICION DE CONSTANTES

 SYMBOL transmito 1  "constante usada para conmutar la transmision/recepcion
 SYMBOL recibo    0  " "    "            
 SYMBOL apagado   0  "constante para apagar los led
 SYMBOL encendido 1  "constante para encender los led
 "symbol SDA = ORTC.4  "Data I2C
 "symbol SCL = PORTC.3  "Clock I2C
 SYMBOL LED = PORTC.5 "Led rojo
 SYMBOL RELOJ = PORTD.1
 
 SYMBOL NOT_RBPU = OPTION_REG.7 " PORTB Pull-up Enable
 SYMBOL RBIF = INTCON.0 " Flag de interrupcion del puerto B
 SYMBOL RBIE = INTCON.3 " RB Port Change Interrupt Enable
 SYMBOL GIE = INTCON.7  " Global Interrupt Enable


"DEFINICION DE VARIABLES  
 DIM tempo8 AS  BYTE  "Variable temporal tipo byte
 DIM tempo16 AS WORD  "Variable temporal tipo Word
 DIM direccion AS BYTE
 DIM dato AS BYTE
 
"DEFINICION DE LOS PINES DE ENTRADA/SALIDA.

ADCON1 = 7     "PORTA y PORTE como I/O digitales

TRISA=%00000000   "Los pin PORTA son salidas
TRISB=%00010000   "Los pin (PORTB.4) son entradas.
TRISC=%10000000   "Los pin  son SALIDAS.
TRISD=%00000000   "Los pin  son SALIDAS.

"eeprom 0,[0,0,0,0,255,4,3,1,0,1,0]  "Configuración activa
"Posicion 0,1,2,3,4 --> 4 bytes para serializar cada micro
"Posicion 4-----------> Direccion logica, del 128 al 254 (255 es broadcast)
"Posicion 5-----------> Distancia umbral, por defecto 4 (2 metros)
"Posicion 6-----------> Veces seguidas que la sonda debe medir para considerar
                       "un cambio de estado en la medicion. Por defecto 3 veces
"Posicion 7,8,9 ------> Version del firmware
"Posicion 10----------> 7 6 5 4 3 2 1 0 Byte en el que guardo varias cosas:
"    En el Bit 0 -->variable apagada, por defecto 0 (que significa encendida)
"    En el Bit 1 -->bit que indica bloqueo, por defecto 0
"    En el Bit 2 -->bit que indica el tipo de bloqueo: 1->bloqueo verde, 0->bloqueo rojo. Por defecto 0
"    En el Bit 3 -->bit de límite de tiempo sobrepasado. 1->sobrepasado,0->no sobrepasado
"    En el Bit 4 -->bit de control de salida auxiliar 1. Por defecto 0 (apagado)
"    En el Bit 5 -->No usado, por defecto 0
"    En el Bit 6 -->No usado, por defecto 0
"    En el Bit 7 -->No usado, por defecto 0







"eeprom 48,[0,0,0,0,255,4,3,1,0,1,0]  "Guardo la configuración de fábrica

"GAMBOA FIRMWARE identificacion
EWRITE 240,[255,71,65,77,66,79,65,32,70,73,82,77,87,65,82,69]

GOTO   main "Me voy al comienzo del programa


"Activo la interrupción del PortB
 
"INTCON = $88 " habilito interrupcion global y cambio en Port B
"ON INTERRUPT GOTO int_tecla



INT_tecla:    "Rutina de servicio de interrupción
   GIE = 0  " Deshabilito la interrupción global
   INC dato
   direccion= %01110010
   tempo8=dato
   HBUSOUT direccion, [tempo8]
   WHILE 1=1
    IF PORTB.4=1 THEN BREAK "espero a que la tecla se deje de pulsar
   WEND
   RBIF = 0 " Borro Flag de interrupcion del puerto B
   GIE = 1  " Habilito la interrupción global
   
CONTEXT RESTORE

main:   "Prohrama principal
 NOT_RBPU=0 "Activo las resistencias internas de pullup puerto B
 RBIF = 0 " Borro Flag de interrupcion del puerto B
 RBIE = 1 " Habilito la interrupcion local del puerto B
 GIE = 1  " Habilito la interrupción global
 tempo8=0
 direccion=0
 dato=0
 RSOUT "GAMBOA FIRMWARE"
 
 direccion= %01110010  "Apago los led
 tempo8=%11111111
 GOSUB escribir_PCF

   
" ** PROGRAMA PRINCIPAL **


 WHILE 1=1
    LED=~LED
    FOR tempo16=1 TO 500
        DELAYMS 1
        RELOJ=~RELOJ
    NEXT tempo16
    direccion=%01110001
    GOSUB leer_PCF
    RSOUT BIN8 tempo8,10,13
    IF tempo8.0=0  THEN
"      INC dato
"      direccion= %01110010
"      tempo8=dato
"      GOSUB escribir_PCF
    ELSE
"      direccion= %01110010
"      tempo8=%11111111
"      GOSUB escribir_PCF
    ENDIF
       

 WEND

"*************************************************************************
"** SUBRUTINA: leer_PCF
"** lee uno de los expansores de bus
"*************************************************************************


leer_PCF:
    HBUSIN direccion, [tempo8]
    RETURN
   
"** FIN SUBRUTINA: leer_PCF


"*************************************************************************
"** SUBRUTINA: escribir_PCF
"** lee uno de los expansores de bus
"*************************************************************************


escribir_PCF:
    "tempo8=$00
    HBUSOUT direccion, [tempo8]
"    BSTART
"    BUSOUT %01110000
"    BUSOUT tempo8
"    BSTOP
     
    RETURN
   
"** FIN SUBRUTINA: escribir_PCF


""*************************************************************************
""** SUBRUTINA: int_tecla
""** Rutina de manejo de interrupción
""*************************************************************************

"DISABLE   "desactivo la interupción, durante la gestion.
"int_tecla:
   
"    FOR tempo8=1 TO  10
"    LED= encendido
"    FOR tempo16=1 TO 50
"        pause 1
"    NEXT tempo16
"    LED= apagado
"    FOR tempo16=1 TO 50
"        pause 1
"    NEXT tempo16
"    NEXT tempo8
   
   
"    i2cread SDA, SCL,%01110001, [tempo8]
"    INTCON.0=0 "limpio el flag de la interrupción
"    RESUME
   
""** FIN SUBRUTINA: int_tecla



END


Espero que te sirva de pauta.

Para la interrupción externa tienes el registro INTCON y los bits de ese registro  INTF, e INTE.  Esto para un 877. Para un 84 es el mismo registro, aunque pueden cambiar la posición de los bits. Eso lo puedes confirmar en el data SHEET

Saludos
Ricky
Madrid-España

Desconectado khasistos

  • PIC18
  • ****
  • Mensajes: 493
RE: on interrupt
« Respuesta #2 en: 24 de Noviembre de 2004, 18:57:00 »
Hola.

primero no te asustes con el ejemplo que te mando RGL la mayoria de las cosas innecesarias para ti estan anuladas con el prefijo  " asi que esas solo ocupan lugar y no son de tu interes solo parece un programa gigante pues se tomo la molestia de anularte las que no eran utiles para ti puedes sacarlas todas las que tengan el " delante....

depende que tipo de interrupcion uses podras o no salir de una pausa ,si lo que usas es una verdadera interrupcion por hardware ,tipo ON INTERRPT en PBPLUS no habra nada que te lo detenga saltara asi este dentro de una pausa....ahora si utilizas una interrupcion por soft tipo ON_INTERRUPT (la diferencia en el guion bajo) esa si esperara que se cumpla el tiempo establecido en la pausa y luego saltara.....todo esto que te comento en PLUS no se si el PRO tiene lo mismo Ricky RGL nos lo podra aclarar....
Hay post en este mismo subforo con abundancia de ejemplos .....

saludos

Khasistos

Desconectado lager

  • PIC18
  • ****
  • Mensajes: 258
RE: on interrupt
« Respuesta #3 en: 24 de Noviembre de 2004, 19:02:00 »
picoffon,
No se que herramienta de compilacion uses, pero para proton te recomiendo leas el post hecho por el pana Khasistos, aqui:
http://miarroba.com/foros/ver.php?foroid=8826&temaid=2661542
Es TODO sobre interrupciones y sus problemas con las variables de sistema, es necesario que lo leas bien para que no tengas problemas con estas V.S
Salu2 pana

Desconectado Picoffon

  • PIC10
  • *
  • Mensajes: 19
RE: on interrupt
« Respuesta #4 en: 25 de Noviembre de 2004, 03:48:00 »
Muchas gracias a todos. En un principio he de reconocer que me había asustado un pelín al ver el programa de RGL, pensaba que no sería muy difícil el tema de las interrupciones, y de repente me veo ese peazo programa. Gracias RGL por señalar las lineas que no me eran necesarias (todo un detalle).

Respecto al compilador, uso Pic basic Pro. Espero que ambas instrucciones (on interrupt y on_interrupt) funcionen de la misma manera que en el Plus. De todas maneras, ahora mismo voy a mirarme el post de Khasistos para ver si salgo de dudas con todo esto de las interrupciones.

Nota: A ver si alguien puede confirmar si lo de "on interrupt" funciona de la misma manera en el Pro que en el Plus.

Desconectado RGL

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 634
RE: on interrupt
« Respuesta #5 en: 25 de Noviembre de 2004, 04:07:00 »
En PBP no es del todo igual. Solo existe interrupción por software y hay tiempo de latencia en un pause. Normalmente este tiempo de latencia (o de espera para que se termina lo que se está haciendo, por ejemplo un pause) es un efecto indeseado en una interrupción que lo que quieres es que sea rápida.

Ahora es que me he cambiado al protón y me gusta más que el PBP (gracias a los panas Lager y Khasistos).

Para ver ejemplos fáciles de interrupciones con PBP te recomiendo vayas a la página www.melabs.com, ahí hay ejemplos cortos muy ilustrativos de cada comando incluidas las interrupciones.

Para aclararte un poco en PBP cambia un poco la sintaxis pero es muy parecida la estructura al ejemplo que antes hemos puesto en Plus.

Saludos
Ricky
Madrid-España

Desconectado Picoffon

  • PIC10
  • *
  • Mensajes: 19
RE: on interrupt
« Respuesta #6 en: 25 de Noviembre de 2004, 04:21:00 »
LlorandoUff, como no se pueda interrumpir el programa en mitad de una pausa me parece que tendré que plantearme otro tipo de instrucción. Solo espero no tener que recurrir a ensamblador por que si no ya si que me voy a marear. Continuaré investigando a ver que pasa.

Desconectado RGL

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 634
RE: on interrupt
« Respuesta #7 en: 25 de Noviembre de 2004, 04:26:00 »
Si tienes que interrumpir en PBP en una pausa tienes que hacer la interrupción en ensamblador.


Hay trucos y es utilizar PAUSEUS  dentro de un FOR NEXT muchas veces, entonces tus intrucciones tardan muy poco en hacerse y por lo tanto el tiempo de latencia se disminuye. Pero tienes que calcular la velocidad de respuesta de tu aplicación, no es lo mismo un teclado que es muy lento que un ABS que debe ser muy rápido.

Saludos
Ricky
Madrid-España

Desconectado Picoffon

  • PIC10
  • *
  • Mensajes: 19
RE: on interrupt
« Respuesta #8 en: 25 de Noviembre de 2004, 04:58:00 »
Eso del bucle "for" lo pense al principio antes de meterme con la instrucción "On interrupt". De hecho, fue una de mis cuestiones en el foro para ver si funcionaba de esa manera. Si miras el post "Funcionará esto así?" lo verás. De todas maneras te pongo el código que puse de ejemplo a ver:

for i=1 to 60000
if pulsador1=1 then CICLO_T1
pauseus 1
next i
for i=1 to 30000
if pulsador1=1 then CICLO_T1
pauseus 1
next i

Supongo RGL, que te referías a algo similar. El caso es que ¿funcionará con suficiente precisión?. Esa es la duda. Tal vez haciendo pausas todavía más pequeñas, pero no se si me dejará el PBPro.

Desconectado RGL

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 634
RE: on interrupt
« Respuesta #9 en: 25 de Noviembre de 2004, 08:46:00 »
PBP no te deja pausas más pequeñas de 1 microsegundo de esta manera. Pero depende de la rapidez que necesites 1 microsegundo puede ser mucho o poco. Eso solo depende de lo que tu necesites.

Yo en vez de hacer esos bucles que tu sugieres, que no entiendo muy bien la finalidad de ellos, creo que se prodría encarar de otra forma el tema.

for i=1 to 60000
 if pulsador1=1 then CICLO_T1
 pauseus 1
next i

 for i=1 to 30000
 if pulsador1=1 then CICLO_T1
 pauseus 1
next i

Por lo que veo los for por 60000 y por 30000 hacen un total de un for de 90000 que equivale a un tiempo. Es decir estás chequeando una entrada durante un minuto con pausas de 1 microsegundo. No entiendo lo de la pausa de 1 microsegundo para que sirve.

Yo haría lo siguiente:

1.- hago un bucle infinito por ejemplo con un while 1 donde chequeo el pulsador.
2.- Por interrupción del timer 0 o del TMR1 cuento el tiempo necesario  equivalente a ese for 90000.

Por lo tanto no la pulsación la recibirás inmediatamente y cuando haya transcurrido ese minuto pues haces otra cosa. No se si esta forma de encarar el tema te lía más o te abre nuevos caminos.

Saludos
Ricky

Desconectado Picoffon

  • PIC10
  • *
  • Mensajes: 19
RE: on interrupt
« Respuesta #10 en: 26 de Noviembre de 2004, 05:14:00 »
Lo de las pausas de un microsegundo, he de reconocer que me he pasado un pelín haciéndolas tan pequeñasGiño. Pensándolo mejor haría una pequeña modificación en el bucle:

for i=1 to 900
if pulsador1=1 then CICLO_T1
pauseus 100
next i

De esta manera creo que sería más que suficiente. El caso es que, lo que yo quiero hacer, es que al pulsar un pulsador, se genere un 1 en la entrada del pic a la que he llamado "pulsador1". Este pulsador se puede pulsar en cualquier momento y por lo tanto, si yo lo pulsase en el momento en el que entra en una pausa de minuto y medio, no reacionaría hasta que saliera de la pausa, y eso no me interesa. Por eso viene lo de las pausas tan pequeñas, para que de puedan detectar las pulsaciones al tiempo que se pulsan. Se que es una manera un tanto chapucera, pero me parece más sencillo que utilizar el timer 0, ya que hay que ir calculando el tiempo para el desbordamiento del timer, y la verdad es que todavía no controlo demasiado en ese aspecto.

Si no me funcionase el bucle ya me miraría bien como hacer lo que tu dices RGL.


 

anything