Autor Tema: deshabilitar interrupciones  (Leído 11446 veces)

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

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
deshabilitar interrupciones
« en: 22 de Febrero de 2007, 20:14:15 »
hola! tengo una pequeña dudilla de nada...
estoy haciendo un programa que tiene que estar pendiete de un boton... y para no dejar el micro en un bucle infinito le puse una interrupcion externa... ahora, quiero que una vez que se ejecute la interrupcion no pueda ser interrumpida por presionar otra vez el boton antes de que acabe la ejecucion de la primera...
es decir, lo que quiero es que al pulsar un boton ocurran unas cosas, pero esas cosas no se puedan interrumpir si vuelvo a presionar el boton. estuve pensado y no se si se podria deshabilitar las interrupciones dentro de una interrupcion, asi:
Código: [Seleccionar]
#int_ext
boton(){
disable_interrupts(int_ext);

CODIGO

enable_interrupts(int_ext);
}

void main(void)
{
   enable_interrupts(int_ext);      //activar interrupcion externa
   ext_int_edge(L_TO_H);         //configuracion:interrupcion solo de LO a HIGH
   enable_interrupts(GLOBAL);      //todas las interrupciones activadas
}

es esto posible?
esta bien empleado?
gracias!!!!  :mrgreen:
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: deshabilitar interrupciones
« Respuesta #1 en: 22 de Febrero de 2007, 23:00:27 »
Si el GIE está deshabilitado, no ocurrirá ninguna interrupción.

Los pics 16F son "monointerrupción", solo pueden atender una por vez.  Si llega otra cuando atendió la primera no se interrumpirá la ejecución del software.

Al ocurrir una interrupción, el pic modifica el Program Counter y queda en 0x0004.  También deshabilita el GIE, con lo cual no ocurrirá otra interrupción.

Cuando sales del vector de interrupción, debes hacer un RETFIE que precisamente significa "Retornar de la interrupción y habilitar las interrupciones" .

Saludos
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: deshabilitar interrupciones
« Respuesta #2 en: 23 de Febrero de 2007, 10:47:39 »
Como te dijo Maunix los pic16 tienen un solo vector de intrrupciones ubicado en 0x0004, eso quiere decir que cuando cualquier interrupción se produce, el micro espera a que termine la instrucción que está ejecutando en ese momento, mete el contador de programas en la pila y luego cambia el contador de programas para la dirección 0x0004. Este proceso hace que la ejecución del código comience en 0x0004 y es en este lugar donde tienes que discriminar cual fue la interrupción que entró.

Puede darse el caso de que hayan varias interrupciones habilitadas y marcadas a la vez, entonces aquellas que pongas primero en la lisa de preguntas serán las más prioritarias. Este mecanismo funciona más o menos así:

Cada fuente de interrupción tiene un registro de habilitación (pude ser un bit o más de uno dependiendo de como se configure la IT y de su tipo), un circuito de detección y una bandera de interrupción (sirve para marcar que las condiciones para la IT ocurrieron). Cada uno de estos elementos juega un papel en el mecanismo de IT, sin embargo es la bandera la que determina si la IT se produjo o no, normalmente cuando entras en la dirección 0x0004, el procesador deshabilita TODAS las IT (modificando GIE) y cuando retornas con RETFIE, la vuelve a habilitar, si durante la ISR se produjo otra IT, entonces se vuelve a entrar en 0x0004 y así hasta que no quede ninguna IT, pero esto a veces no es deseable porque puedes demorar mucho tiempo atendiendo una IT y otra más prioritaria puede entrar sin que se atienda debidamente, por ejemplo en conversor AD puede hacer varias conversiones que se pierdan mientras atiendes otra IT.

La idea anterior es que durante la atención a una IT, otra no pueda ser atendida. Sin embargo puede darse el caso de que el compilador de C habilite nuevamente las IT cuando entras en la ISR, para que otra IT pueda interrumpir mientras atiendes a una que llegó antes, entonces tendrías dos IT anidadas, eso puede ser deseable, pero en el caso de una tecla no lo es porque estarías bajo los efectos del rebote, para evitar este único efecto y mantener el resto de las IT habilitadas (permitir el anidamiento de IT), solamente debes cambiar la configuración de la IT asociada a tu tecla para que esté deshabilitada, mientras mantienes el resto habilitadas (el conversor AD, el puerto serie, etc). Si lo que deseas es que nada te interrumpa mientras atiendes la tecla, entonces deshabilitas todas las IT a traves de GIE.

Este análisis debes hacerlo cuidadosamente porque puede darse el caso de que se afecten otras partes de tu programa. Por ejemplo si entra un dato por el puerto serie y estás atendiendo a la tecla, lo cual te puede tomar unos 30ms para eliminar el rebote y demás, puede que pierdas un grupo de datos del puerto serie si tienes TODAS las IT deshabilitadas, sin embargo si solamente deshabilitas la IT de la tecla y entran los datos por el puerto serie, podrás atender a esta IT más prioritaria dentro de la IT de la tecla y no perder los datos. Piensa y busca la solución adecuada a tu problema

Reinier


Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: deshabilitar interrupciones
« Respuesta #3 en: 23 de Febrero de 2007, 11:52:15 »
 :shock:
ufff.... me acabais de dar un repaso que todavia estoy intentando recuperarme  :z)
No entendi ni papa
esperad que voy a ponerme a investigar un poco...
...
...
...
OK!  :-/
Ahora entiendo un 7% mas que la primera vez que lei vuestras respuestas...
Lei un datasheet y algo que encontre por internet...
Primero, IT es la abreviacion de interrupcion, no? y GIE habilitada o deshabilitada es como poner enable/disable_interrupts(global)?
La GIE como comentais, se deshabilita cuando hay una interrupcion?
Yo solo quiero que se deshabilite la interrupcion externa para que no se pueda volver a apretar el boton mientras se ejecuta. pero quiero que sigan funcionando las interrupciones por tmr, adc o lo que sea.
no se como implementar esto que me comentais, ni si tengo que poner ¿retfie? al final de las instrucciones de mi interrupcion
alguna ayudita mas?  :mrgreen:
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: deshabilitar interrupciones
« Respuesta #4 en: 23 de Febrero de 2007, 12:34:06 »
disable_interrupts (INT_EXT) te deshabilita la interrupción externa y con enable_interrupts (INT_EXT) la vuelves a habilitar. Que no se te olvide volver a habilitar la IT cuando atiendas a la tecla o adios a la tecla


Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: deshabilitar interrupciones
« Respuesta #5 en: 23 de Febrero de 2007, 13:04:01 »
entonces el codigo que puse en el primer post seria correcto....
deshabilitar las int_ext cuando entro en la interrupcion, y habilarlas en la ultima linea de codigo de esa int?
salu2 y gracias
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: deshabilitar interrupciones
« Respuesta #6 en: 23 de Febrero de 2007, 13:36:10 »
entonces el codigo que puse en el primer post seria correcto....
deshabilitar las int_ext cuando entro en la interrupcion, y habilarlas en la ultima linea de codigo de esa int?
salu2 y gracias

Si el PIC entra en la interrupción se deshabilita el GIE.  Entonces, no hay necesidad de deshabilitar nada.

Saludos


- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: deshabilitar interrupciones
« Respuesta #7 en: 23 de Febrero de 2007, 14:18:37 »
Si pero el quiere mantener el resto de las interrupciones habilitadas mientras atiende la interrupción de la tecla (INT_EXT), así que debería hacer un código más o menos así

Código: C++
  1. /* Esta es mas o menos la funcion de atender la IT externa, nota como esta se
  2. encarga solamente de poner una bandera en '1' y deshabilita esta misma IT para
  3. luego retornar. Cuando sales de la ISR GLOBAL, todas las IT quedan nuevamente
  4. habilitadas, es tarea del programa principal atender a la tecla. Es decir: eliminar
  5. el rebote, leer puertos y demas cosas que hay que hacer cuando te aprietan una tecla
  6. no debe ser tarea de la funcion de atencion de la IT porque la idea de un buen
  7. diegno utilizando IT es que las rutinas de IT sean cortas y que solamente cambien
  8. algunos parametros o banderas para que otra parte del programa se haga cargo de
  9. procesar esas informaciones.
  10.  
  11. Otra razon que obliga a que las subrutinas de atencion a IT sean cortas es porque
  12. en casos como este de la tecla debes eliminar rebotes y lo mejor para hacerlo, desde
  13. mi punto de vista, es emplear un Timer y ese segnor tambien trabaja con IT. Entonces
  14. volvemos al asunto de dejar en manos del programa principal la atencion de las
  15. tareas que hay que hacer cuando se apriete una tecla
  16. */
  17. #INT_EXT
  18. void int_ext_isr(void)
  19. {
  20.  disable_interrupts(INT_EXT); //deshabilitar la IT externa
  21.  
  22.  FlagTecla = 1; //marcar la tecla como oprimida
  23.  
  24. }
  25.  
  26. /*
  27. Luego en el programa principal es donde habilitas nuevamente la IT, una vez que
  28. hayas atendido la tecla, para que cuando vuelvan a apretar la tecla se pueda
  29. procesar nuevamente
  30. */
  31.  
  32. void main(void)
  33. {
  34.   ... //Codigo que no atiende la tecla
  35.  
  36.  if(FlagTecla and Paso_el_Rebote)  //Preguntar por la tecla y si ya paso el tiempo del rebote
  37.     {
  38.      ... //Codigo para procesar la tecla
  39.      FlagTecla = 0;  //Poner las banderas en el estado de tecla no apretada y rebote no procesado
  40.      Paso_el_Robote = 0;
  41.      enable_interrupts(INT_EXT); //Ya se puede procesar otra tecla
  42.     }
  43.    
  44.  ...  //Codigo que no atiende la tecla  
  45.    
  46. }


Esta no es la única forma que existe para hacer eso, se pueden utilizar otros mecanismos, más o menos elaborados para ello. Por ejemplo puedes hacer todo el proceso de atender la tecla dento de int_ext_isr() y habilitar las interrupciones globales para que haya anidamiento de IT, pero esa técnica te puede traer problemas, sobre todo porque la pila de los PIC es bastante pequeña y es un recurso que debemos vigilar constantemente. También puedes utilizar un RTOS que te puede ayudar a simplificar mucho el trabajo, etc.

Tú eres quien tiene que decidir cual es el mejor método para hacer el trabajo o cual te da mejores resultados sin complicarte mucho.

Un saludo Reinier

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: deshabilitar interrupciones
« Respuesta #8 en: 17 de Marzo de 2007, 17:45:55 »
Código: C++
  1. #INT_EXT
  2. void int_ext_isr(void)
  3. {
  4.  disable_interrupts(INT_EXT); //deshabilitar la IT externa
  5.  
  6.  FlagTecla = 1; //marcar la tecla como oprimida
  7.  
  8. }
  9.  
  10. void main(void)
  11. {
  12.   ... //Codigo que no atiende la tecla
  13.  
  14.  if(FlagTecla and Paso_el_Rebote)  //Preguntar por la tecla y si ya paso el tiempo del rebote
  15.     {
  16.      ... //Codigo para procesar la tecla
  17.      FlagTecla = 0;  //Poner las banderas en el estado de tecla no apretada y rebote no procesado
  18.      Paso_el_Robote = 0;
  19.      enable_interrupts(INT_EXT); //Ya se puede procesar otra tecla
  20.     }
  21.    
  22.  ...  //Codigo que no atiende la tecla  
  23.    
  24. }

reiniertl, entiendo el codigo que pusiste. lo que no me queda claro es si al salir de int_ext_isr vuelve al inicio del main, segun leo el codigo parece que debe ser asi, sino no veo la manera de que funcione. y de ser asi, porque al acabar el isr continua al inicio del main?
lo que tampoco me queda claro es lo de Paso_el_rebote, en que momento se pone a 1? de hecho no comprendo muy bien que es el rebote y como evitarlo
gracias y salu2
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado vszener

  • Moderador Local
  • PIC24H
  • *****
  • Mensajes: 2395
Re: deshabilitar interrupciones
« Respuesta #9 en: 18 de Marzo de 2007, 09:06:56 »
Como ya te han dicho, cuando se produce una interrupción, el GIE se pone a 0, por lo que no puede haber ninguna otra interrupción.

Aunque si te queda más claro poner el disable_interrupts(); lo pones, simplemente lo que haces es reescribir un 0 al GIE.


Suerte!!! ;)
· Nos vemos en los bares!!!!!
· Mi Blog: Aqueronte

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: deshabilitar interrupciones
« Respuesta #10 en: 19 de Marzo de 2007, 14:50:54 »
reiniertl, creo que ya entendi tu codigo!  :mrgreen:
le faltaria un bucle infinito al main para que este constantemente verificando si se produjo o no una INT_EXT, no?
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: deshabilitar interrupciones
« Respuesta #11 en: 19 de Marzo de 2007, 16:01:27 »
Parece que no has comprendido bien el mecanismo de interrupción. Te lo explico un poco mejor:

Imagina que el PIC está ejecutando un programa, ejecutará las líneas de código de forma secuencial, hasta que encuentra un salto a alguna parte del código, por esta razón es que main() debe tener un ciclo infinito, para asegurar que al terminar de ejecutar las líneas de código de main(), el programa comience nuevamente por el principio. Si no se hace así el PIC continuará "ejecutando" código hasta que llegue al final de su espacio de direcciones y se quede zoombie.

Bien, lo anterior explica como funciona un programa cualquiera, si tienes intención de atender periféricos con un programa así, se dice que estás atendiendo al proceso por encuesta, ya que en alguna parte del código preguntarás por el estado de algun registro para en función del resultado ejecutar una acción. Este mecanismo es ineficiente y muchas veces no puede ser utilizado porque hay procesos que duran muy poco en el tiempo y necesitan ser atendidos rápidamente, para ello existen los mecanismos de interrupción.

Cada vez que el PIC ejecuta una instrucción, antes de cargar la que le sigue, primero chequea si se ha producido una interrupción, si es así, entonces mete el Contador de programas  (CP) en la pila (el CP apunta a la instrucción que debe ejecutar el procesador en el programa normal), y carga una dirección fija en el CP, en este caso 0x0004h y carga la instrucción que se encuentra en esta dirección. Has entrado en la ISR (Interrupt Service Routine), cuando terminas de ejecutar este código, la última intsrucción tiene que ser retfie, para que el PIC saque de la pila el valor del CP que estaba antes de que se atendiera a la interrupción.

Claro el compilador de C, hace parte del trabajo por tí y te evita tener que fajarte con salvar registros que utilizas dentro de una ISR, pone por tí código para retornar de la interrupción, etc.

La directiva #int_ext le dice el compilador que la función que le sigue en el código es la subrrutina de atención a la interrupción externa. Esto quiere decir que cuando se produzaca esta interrupción se ejecutará el código de esta función y cuando se termine de ejecutar se retorna al punto del programa donde se produjo la interrupción. Cuando se produce una interrupción: ¡NADIE SABE!, lo que si debemos asegurar es que se atienda lo más rápido posible.

Lo otro de trabajar con interrupciones es que la sbrutina de atención debe ser LO MÁS CORTA POSIBLE, eso quiere decir que debemos separar lo esencial del proceso de atención de las cosas que debemos hacer en consecuencia. Por ejemplo una ISR para atender al converor AD, quizás solamente deba leer el dato del resultado, cambiar el canal y dar nuevamente inicio de conversión, el programa principal se encargará de procesar los datos y hacer algo con el resultado de ese procesamiento, no debemos poner todo el código de actuación ante una interrupción en la ISR porque muchas de las cosas que hagamos ante una interrupción no requieren que se actúe de inmediato, aunque si hay que atender las cosas esenciales a la mayor brevedad posible.

En el caso de lo que pretendes hacer la INT_EXT te permite saber que se apretó una tecla, y con eso le indicas al programa principal (el que está dentro de main()) que se apretó la tecla para que sea este código quien actúe en consecuencia. El uso de la Interrupción te permite que no se pierda la pulsación de una tecla, ya que si tu programa está haciendo algo que consume tiempo, es posible que la tecla se apriete y se suelte y tu PIC no se de cuenta, aunque esto es poco probable que ocurra con una tecla, hay procesos que son bastante rápidos y eso puede ocasionar que se pierda información o no se tengan encuenta determinados procesos.

Reinier

Desconectado Marttyn

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1835
    • IDEAA
Re: deshabilitar interrupciones
« Respuesta #12 en: 19 de Marzo de 2007, 16:32:05 »
pues con todo esto me has aclarado un monton de oscuros rincones de los pics. pero con lo de un bucle infinito en el main para ver si acurrio una int_ext me referia que el bucle lo que comprobaba era si se habia marcado el flag de que hubo una interrupcion y que se actue en consecuencia, aunque lo principal como marcar el flag, comprobar el adc, guardar un valor o lo que sea lo haga la propia interrupcion.
La gente ve las cosas que existen y se pregunta por qué.
Yo prefiero imaginar lo que no existe y preguntarme por qué no.

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: deshabilitar interrupciones
« Respuesta #13 en: 19 de Marzo de 2007, 17:26:34 »
En lo anterior estás en lo cierto, lo que hace main() es comprobar si se produjo la INT y la INT_EXT lo que hace es setear la bandera.

Desconectado hammerEQ

  • PIC10
  • *
  • Mensajes: 3
Re: deshabilitar interrupciones
« Respuesta #14 en: 05 de Abril de 2007, 19:12:24 »
Hola. hablando de las interrupciones y todo eso. Estoy empezando a trabajar en el PICC de CCS y tengo una duda. ¿ para que las banderas de interrupciones(p.e. TOIF, RBIF, INTF, etc) cambien de estado, es necesario que las opciones de habilitacion de las interuciones esten habilitadas ? (cosa que no pasa con assembler o el C de HI TECH, ya que las banderas se activaran asi no esten habilitadas las interruciones). Gracias.


 

anything