Autor Tema: Interrupciones duda  (Leído 2534 veces)

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

Desconectado fitson

  • PIC10
  • *
  • Mensajes: 38
Interrupciones duda
« en: 05 de Diciembre de 2016, 06:55:29 »
Hola tengo una pregunta para utilizar interrupciones , ya que yo he sido de CCS y antes utilizaba
por ejemplo esta función

Código: [Seleccionar]
#INT_EXT
función (){
    código
}

y con esto yo podía acceder a la función una vez ha saltado la bandera.
Y cada compilador utiliza funciones distintas.

Pero ahora quiero saber como se podría expressar #INT_EXT de otro modo sin utilizar la función predefinida,
más que nada es para entender como es esto de que el programa sabe que tiene que ir hacia esa función cuando el flag se pone a 1.

gracias.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Interrupciones duda
« Respuesta #1 en: 05 de Diciembre de 2016, 08:23:06 »
Citar
Y cada compilador utiliza funciones distintas.

En realidad CCS es el unico que usa una "funcion" distinta. Todos los demas se parece mucho mas a como el hardware funciona. Cuando se produce una interrupcion, el PIC internamente salta a la posicion de memoria 0x04 en los PIC16 y 0x8/0x16 para los PIC18 (no recuerdo si eran esos valores exactos de los PIC18). Una ves que llegan ahi lo que queda hacer es preguntar uno por uno los flags y si entro hay que limpiarlos, esto es a cargo de la persona.

Ejemplo en XC8 harias esto:

Código: C
  1. void interrupt funcion_int(void)
  2. {
  3.       if(INTCONbits.T0IF)
  4.       {
  5.            //Programa
  6.            INTCONbits.T0IF = 0
  7.        }
  8.       if(INTCONbits.RB0IF) // Tu INT_EXT
  9.       {
  10.            //Programa
  11.           INTCONbits.RB0IF = 0;
  12.       }
  13. }

obviamente es void, porque es una funcion que no tomaria ningun argumento ni devolveria valor. El "interrupt" lo unico que hace es ubicarlo sobre la posicion 0x4. Lo demas es como funcionaria y es lo mismo que tenes en CCS, nomas que en CCS lo tenes "oculto" a la vista, por eso nunca limpias el flag ( o al menos no hay necesidad ) y tenes esas directivas de preprocesamiento como #INT_TMR0, y no necesitas estar preguntando por cada flag.

Para hacer lo que queres, deberias forzar al compilador para que posicione una funcion en la direccion 0x4, lo cual no creo que se pueda. Segundo tenes que acceder a bits en los registros, por lo cual vas a tener que definir los registros en CCS, mas trabajo. Resumen, tenes que usar eso como te lo da CCS.

Desconectado fitson

  • PIC10
  • *
  • Mensajes: 38
Re:Interrupciones duda
« Respuesta #2 en: 05 de Diciembre de 2016, 20:18:27 »
si se activan 2 o 3 interrupciones al mismo tiempo que pasaría entonces?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Interrupciones duda
« Respuesta #3 en: 05 de Diciembre de 2016, 20:40:50 »
si se activan 2 o 3 interrupciones al mismo tiempo que pasaría entonces?

Depende del integrado.

Los PICs mas basicos al momento de saltar a la direccion 0x04 desactivan todas las interrupciones, es decir ponen el bit GIE del registro INTCON en 0.
Por lo cual si ocurre otra interrupcion mientras se atiende una, esta no es atendida. Por eso mismo uno no debe poner delays o funciones que duren demasiado tiempo en una interrupcion, a no ser que este seguro de que no produzca nada, ejemplo un delay en la interrupcion de un timer y ademas usamos la interrupcion para recibir por la UART, mientras se encuentra ejecutando el delay van a llegar datos por la UART y nunca se van a sacar, por lo cual se termina con un ERROR de OVERRUN y perdiendo datos. Ya que estas evitando que las demas interrupciones puedan ser atendidas.
Para salir de la interrupcion se ejecuta una instruccion especial que hace que vuelva donde estaba y ademas pone el bit GIE en 1. Habilitando de nuevo, como el flag de la interrupcion que sucedio no se puso en 0, automaticamente salta de nuevo a la direccion 0x04 para ejecutar de nuevo toda la rutina de interrupcion pero esta vez entraria en la otra interrupcion.

Usando el codigo que pase, puede darse la casualidad que antes que termine el primer if ocurra la interrupcion, asi que cuando pregunta por el otro if entre y lo atienda. Pero esto es un margen MUY pequeño de tiempo normalmente, en el cual se lograria atender a las 2 interrupciones de una sola entrada. Pero mejor asegurarse pensando que tiene que entrar de vuelta.

Los PIC18 tiene 2 vectores. Uno de alta prioridad y otro de baja. Esto permite que si se esta ejecutando un codigo de baja prioridad, y ocurre una de alta tal como ocurriria de programa principal a interrupcion, nomas que aca ocurre de interrupcion a interrupcion, se guarda donde estaba y se atiende el de alta, cuando sale sigue ejecutando el de baja. Si ambas son de la misma prioridad entonces hay que esperar que termine. Esto a nivel de hardware trae un par de mejoras en el que la interrupcion de alta guarda por si solo los registros y en la de baja la persona debe ocuparse de ello (hablando al programar en ASM) en C esto lo hace el compilador y no tenes que preocuparte. Aca cuando habilitas las prioridades, tenes 2 bits como los de GIE, nomas que uno es la habilitacion de prioridad de baja y otro de alta.
Esta opcion de prioridad se puede quitar y que funcione igual que en el caso anterior, los PIC16, etc

En otros PICs como 24F, dsPIC si no mal recuerdo ya las interrupciones tienen un numero de prioridad. Es decir hay mas niveles de prioridad, suponete de 0 a 5. PIC32 lo mismo ocurre.
« Última modificación: 05 de Diciembre de 2016, 21:09:10 por KILLERJC »

Desconectado fitson

  • PIC10
  • *
  • Mensajes: 38
Re:Interrupciones duda
« Respuesta #4 en: 06 de Diciembre de 2016, 11:37:58 »
Entonces Aunque el GIE esta en 0 los registros de los flags pueden cambiar y como bien dices podría producirse en una interrupción más de una función. Lo cual que el GIE se ponga en 0 no implica que bloquee cualquier cambio en los registros flags.

Hay alguna solución para al entrar en una interrupción que entre al if del flag que lo llamo.

Porque como bien dices existe la posibilidad de que el flag 2 haya ejecutado la interrupción pero en un tiempo muy pequeño se ejecuta el flag 1. Si nuestro programa consiste en 2 leds que se encienden indicando el orden en que los flags se han puesto en uno.
El programa fallara porque si nosotros en la dirección de interrupción tenemos:
Código: C
  1. void interrupt funcion(void){
  2.   if(flag1)
  3.  
  4.   if(flag2)
  5.  
  6. }
primero se ejecutara el if(flag1) y despues (flag2) y no respetando el orden que queríamos.

Existe alguna solución para esto?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Interrupciones duda
« Respuesta #5 en: 06 de Diciembre de 2016, 14:33:01 »
Entonces Aunque el GIE esta en 0 los registros de los flags pueden cambiar y como bien dices podría producirse en una interrupción más de una función. Lo cual que el GIE se ponga en 0 no implica que bloquee cualquier cambio en los registros flags.

Exacto, los flags pueden ponerse a 1 tranquilamente que no va a saltar de nuevo al vector de interrupcion (0x04).

Cuando tenes unicamente 1 solo vector de interrupcion como es el caso, la unica forma de crear una especie de prioridad es poniendo el if que queremos que tenga prioridad primero.

De esa forma si decimos que flag1 deberia ejecutarse primero, probemos varios escenarios:

1- flag 1 y 2 no se activan.
2- flag 1  se activa y 2 no.
3- flag 2 se activa  y el 1 no.
4- flag 1 y 2 se activan
5- flag 1 se activa, y flag 2 se activa mientras se ejecuta flag 1
6- flag 2 se activa y flag 1 se activa mientras entra a la interrupcion
7- flag 2 se activa y flag 1 se activa mientras ejecuta flag 2

1- No se activa ninguna , por lo tanto no entra a la interrupcion
2- Entra , ejecut flag1 y sale
3- Entra, ejecuta flag2 y sale
4- Entra, ejecuta flag1 y luego flag2, cumpliendo la prioridad
5- Entra , ejecuta flag 1 y luego flag2 cumpliendo la prioridad
6- Entra , ejecuta flag1 y luego flag2 cumpliendo la prioridad, y se podria tomar como que fue "simultaneo" el activar flag1 y flag2
7- Entra , ejecuta flag2, sale y ejecuta flag1, que si te pones a pensar es correcto, por que flag1 se activo mucho tiempo despues.

Porque como bien dices existe la posibilidad de que el flag 2 haya ejecutado la interrupción pero en un tiempo muy pequeño se ejecuta el flag 1. Si nuestro programa consiste en 2 leds que se encienden indicando el orden en que los flags se han puesto en uno.
El programa fallara porque si nosotros en la dirección de interrupción tenemos:
Código: C
  1. void interrupt funcion(void){
  2.   if(flag1)
  3.  
  4.   if(flag2)
  5.  
  6. }
primero se ejecutara el if(flag1) y despues (flag2) y no respetando el orden que queríamos.

Existe alguna solución para esto?

No estas equivocado. Si flag2 se esta ejecutando, ya flag1 paso. Lo cual se terminaria la interrupcion, saldria y al estar activo todavia flag1 entraria de nuevo.
Si vos decis que flag2 dispara la accion de interrupcion y luego mientras salta al vector de interrupcion y ejecuta algun codigo antes de comenzar a preguntar por los if, flag1 se activa, entonces se considera como que se activaron simultaneamente. Es decir tenes un "margen" en que es imposible diferenciar el tiempo entre ambas para saber cual fue primero.

A medida que avanza la tecnologia. PIC18 -> PIC24/dsPIC -> PIC32
Esta posibilidad disminuye por que las cosas se hacen por hardware pero siempre esta, ya que por ejemplo podrian tardar 12 ciclos de reloj en un micro ARM para entrar y hacer el salto al vector correspondiente. Los PIC18 como decia tiene una funcion de guardado automatico de registros, por lo cual no tenes instrucciones antes de esos if. A lo sumo un salto como maximo.