Autor Tema: interrupciones 16F877  (Leído 4932 veces)

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

Desconectado ignach

  • PIC10
  • *
  • Mensajes: 28
interrupciones 16F877
« en: 24 de Septiembre de 2003, 09:27:00 »
hola¡
Tengo un sistema que utiliza la interrupciones RB4, RB5, RB6, RB7 y RBO... del 16F877...no he  programado nunca interrpciones y el manual que tengo no sale na:
* enable_interrupts (GLOBAL);
* enable_interrupts (INT_RB);...
y como se especifica sobre la 0 , 4, 5, 6, 7....?
que mas hay que poner??

Un saludo. Gracias.

Desconectado cucaracha

  • PIC24H
  • ******
  • Mensajes: 1409
    • CUCAWEB
RE: interrupciones 16F877
« Respuesta #1 en: 24 de Septiembre de 2003, 11:07:00 »
Mira, antes de nada, la inerrupción INT (la de RB0) es distinta e independiente de las otras que mencionas. De RB4 a RB7 es la interrupción pon cambio.
Por tanto se activan de manera independiente.
Con la INT/RB0 como es una no hay problema.
Al activar la interrupción en cambio (RB4-RB7) la activas en todos los pines, por tanto debes usarla cuando necesites esas 4 interrupciones, o bien te de igual desperdiciar los pines que no uses de ahí, en el caso que por ejemplo uses sólo dos pines.
Lo que creo preguntas es que como sabes cual a generado la interrupción no?. Pues eso se hace a pelo en la Rutina de Servicio de Interrupción. Una vez se crea una interrupción, el programa salta a la dirección de memoria 04H. Ahí tienes que poner la rutina que comprueba que interrupción a sido la que se ha generado (por si p. ej. usas más de una interrupción, INT, interrupción en cambio, timer...). Entoces salta a la rutina RSI de esa inerrupción.
En tu caso debes comprobar pin a pin cual es el que ha cambiado.
Luego limpias los registros que no se cambién por hardware y vuelves con el programa principal con la instrucción de vuelta de interrupción.
Un saludo!
Saludos desde Huelva (ESPAÑA)

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: interrupciones 16F877
« Respuesta #2 en: 24 de Septiembre de 2003, 11:35:00 »
Cucaracha te lo ha explicado muy bien. Yo te voy a explicar como se hace esto con C de CCS.  

En el main tienes que habilitar el bit global de interrupciones. Se hace con: enable_interrupts (GLOBAL);

A continuación en el mismo main habilitas los bits parciales de las interrupciones:

- enable_interrupts (INT_EXT);   //Interrupción por flanco ascendente o descendente en RB0

- enable_interrupts (INT_RB);    //Interrupción por cambio de estado en líneas RB4-7

- enable_interrupts (INT_RTCC);    //Interrupción por desbordamiento del TMR0

- Hay un mogollón más (25 en total, pg.31 del manual original)

Cuando se produce la interrupción va a buscar la rutina (en este caso del C busca una función) de atención a la interrupción. Esta se pone arriba del main de esta forma:

#INT_EXT

interrupcion_RB0()           //Es un nombre de función
{
    ...
}

O si se tratara de la de RB4-7:

#INT_RB

interrupcionRB4_RB7()           //Es un nombre de función
{
    ...
}


Uf, uf, uf vaya tarde de escritura llevo.

Bueno ahora te toca a tí ponerte a estudiar. Un saludo

PD. Agenciate la traducción en español del manual de CCS, está en el FORO (yo me lo tuve que colar en inglés, sin comentarios)


Desconectado ignach

  • PIC10
  • *
  • Mensajes: 28
RE: interrupciones 16F877
« Respuesta #3 en: 24 de Septiembre de 2003, 11:41:00 »
bua¡...muso tema pa" un novato....ya perdonaras:
osea.... pongo:
eneble_interrupts (GLOBAL);
enable_interrupts (INT_RB);...entonces...
cuando se produzca la interrupcion (RB_4_5_6_7)me llevará a la rutina de la interrupcion que yo he programado....entonces en esta, tengo que incluir una rutina que  compruebe en una direccion  que pin ha sido. ¿En que direccion debo hacer esto? ....
no entiendo lo demas:
"Entoces salta a la rutina RSI de esa interrupción. En tu caso debes comprobar pin a pin cual es el que ha cambiado. Luego limpias los registros que no se cambién por hardware y vuelves con el programa principal con la instrucción de vuelta de interrupción"
Gracias....

Desconectado ignach

  • PIC10
  • *
  • Mensajes: 28
RE: interrupciones 16F877
« Respuesta #4 en: 24 de Septiembre de 2003, 11:52:00 »
...pero con el ccs como se diferencia si es la RB4 o RB5...
pones:
INT_RB
interrupcion_RB4(); /*se diferencia aqui???*/
{
}

Gracias a los dos....Un saludo.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: interrupciones 16F877
« Respuesta #5 en: 24 de Septiembre de 2003, 11:53:00 »
Yo lo que hago es en el while testeo contínuamente las entradas de esta forma:

m=input(PIN_B0);
p=input(PIN_B1);
F1=input(PIN_B2);
etc

Cuando salte a la función de atención a la interrupción lo único que tienes que hacer es testear qué variable es:

if (m && F1)   //Si pulsas marcha y está activado el final de carrera F1 se realizará lo que hay entre llaves
{
    ...
}

No hay que borrar en CCS ningún flag. El CCS es muy listo y lo borra solo

Desconectado ignach

  • PIC10
  • *
  • Mensajes: 28
RE: interrupciones 16F877
« Respuesta #6 en: 24 de Septiembre de 2003, 12:09:00 »
perdona pocher pero no lo entiendo....el while donde lo pones??en  el program princiapal...
siempre que se produzca una interrupcion, sea en el pin que sea(RB_4_5_6_7), te lleva a la misma rutina (INT_RB) no?
no se puede diferenciar entre las RB_4_5_6_7 asi para saber cual a sido ?...(pq en mi stma tego un dispòsitivo en cada pin)
INT_RB
interrupcion_RB4(); /*se diferencia aqui???*/
{
}
interrupcion_RB5();
{
}
perdona...Gracias...

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: interrupciones 16F877
« Respuesta #7 en: 24 de Septiembre de 2003, 12:25:00 »
Te pongo un ejemplo y así lo verás más claro:

//                            P1_6.C

#include <16f84.h>

#use fast_io(B)

#byte port_b = 6

#INT_RB       // Interrupción externa en RB4_RB7                          
interrupcion_RB4_RB7()       // Función de atención a la interrupción
{
        short A,B,E0,E1;
        B = input(PIN_B4);
        A = input(PIN_B5);

   if (E1 && A || !E0 && !E1 )
   {
      E0=1;
      E1=0;
   }

   if (E0 && !B)
   {
      E1=1;
      E0=0;
   }

   output_bit(PIN_B0,E1);     // R=E1;
}

main()
{
           set_tris_b(0xF0);   // RB0-RB3 salidas, RB4-RB7 entradas.
   bit_clear(port_b,0);

           enable_interrupts(GLOBAL);
                enable_interrupts(INT_RB);

          while(1)
                   sleep();
}


Ejem, ejem ... en el while testeo las entradas que no van por interrupción. No es el caso del ejemplo de arriba en el que las dos entradas van por interrupción

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: interrupciones 16F877
« Respuesta #8 en: 24 de Septiembre de 2003, 23:46:00 »
Te dejo el enunciado del problema de arriba, por si quieres simularlo.

Un depósito de agua posee dos detectores de nivel, A (máximo) y B (mínimo).  Está alimentado por una electrobomba, que ha de ponerse en marcha cuando el agua esté por debajo del nivel B y debe pararse cuando el agua alcance el nivel A. En esta posición si abrimos la llave de paso inferior, debe seguir parada hasta que de nuevo el agua esté por debajo de B.

El dibujo, la asignación de E/S y el GRAFCET estan en el documento word.

Un saludo

Desconectado ignach

  • PIC10
  • *
  • Mensajes: 28
RE: interrupciones 16F877
« Respuesta #9 en: 25 de Septiembre de 2003, 02:17:00 »
musa gracias...pocher........y....el RB_isr que se pone a continuacion del #INT_RB.. pa" que sirve?...

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: interrupciones 16F877
« Respuesta #10 en: 25 de Septiembre de 2003, 09:17:00 »
A continuación de #INT_RB hay que poner el nombre de la función.

Yo he puesto en el programa: " interrupcion_RB4_RB7() ", pero puedes ponerle otro nombre, por ejemplo RB_isr()

Eso sí los dos paréntesis del final son obligatorios

Desconectado pikman

  • Moderador Local
  • PIC24F
  • *****
  • Mensajes: 682
RE: interrupciones 16F877
« Respuesta #11 en: 30 de Septiembre de 2003, 16:55:00 »
Bueno, aqui te muestro como lo he usado en mi programa a ver si te aclara un poco ,

No se si es necesario usar los cuatro pines cuando habilitas la interrupcion por cambio, pues puedes usarlas como salidas y cada vez que hagas un cambio de estado en las salidas desahabilitas la interrupcion y listo, pero bueno como tengo un ejemplo aqui te lo pego, y te explico rapidamente, en mi equipo lo que hago es arrancar o para la maquina, son dos pulsadores NA conectados a RB4 y RB5 respectivamente.

Espero que te sirva,

saludos

Ariel

#INT_RB

RB_isr() {                          // selector de operaciones

    cmd=swap(INPUT_B() & 0x30);      
   
    switch (cmd) {

                case 1:             // si es 1 set bandera de parada
                  on=false;
                  stop=1;
                  break;


                case 2:             // si es 2 set bandera de arran.
                  on=true;
                  break;

                case 3:             // si es 3 sale sin hacer nada
                  break;
           }



saludos
PikMan

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2569
RE: interrupciones 16F877
« Respuesta #12 en: 01 de Octubre de 2003, 01:07:00 »
Hola Pickman.

No sé si te he entendido bien, si me equivoco me corriges:

- No es necesario utilizar los 4 pines para disparar la interrupción, con que haya un cambio de estado (0>1 o 1>0) la interrupción se dispara y va a ejecutar la función de atención a la interrupción

- Yo creo que la interrupción se dispara únicamente si RB4-RB7 son entradas y hay un cambio de estado en ellas. Si por ejemplo RB7 fuese salida aunque hubiese un cambio en este pin no se dispararía la interrupción.

- En el ejemplo que pones creo que solo hay una salida (la salida "on", que la asignaras a un pin), entonces la variable stop ¿no se utiliza como salida?
Si tuviera dos salidas "on" y "stop" (caso de un motor comandado por dos contactores para el giro derecha-izquierda) faltaría en el case2 hacer "stop=0" para que no esten las dos salidas activas al mismo tiempo cosa que en el caso de un motor te lo cepillarías.

Bueno Pickman esta es la interpretación que yo le he dado, quizá no sea la correcta. La escritura por ordenador es muy fría y dá lugar en ocasiones a falsas interpretaciones.

Un saludo

Desconectado pikman

  • Moderador Local
  • PIC24F
  • *****
  • Mensajes: 682
RE: interrupciones 16F877
« Respuesta #13 en: 01 de Octubre de 2003, 22:11:00 »
Hola, POCHER,

Si asi es, solo se produce una interrupcion cuando rb4:rb7 son entradas la confuncion me vino porque en una version de mplab el simulador cometia este fallo, por lo tanto rectifico, puede tener por ejemplo rb4 y rb5 como entradas que disparan la interrupcion cuando cambian de estado y rb6 y rb7 como salidas haciendo cualquier cosa, que no disparan la interrupcion por cambio de estado.

En cuanto al ejemplo aqui va comentado


#INT_RB

RB_isr() {                          // selector de ON - OFF

    cmd=swap(INPUT_B() & 0x30);     // carga en la variable cmd el valor del puerto
                                    // enmascarando los bits 4 y 5 que son las botoneras
                                    // luego hace un swap para tener el valor lsb.
    switch (cmd) {

                case 1:             // si es 1 set bandera ON
                  on=true;
                 break;


                case 2:             // si es 2 clear bandera ON
                  on=false;
                  break;

                case 3:             // si es 3 sale
                  break;
           }

     }


Ahora bien, ON es una variable del tipo short, entonces mi programa de funcionamiento esta en un while (on){}
por lo tanto lo que hago es poner en 1 o 0 la variable y de esta manera ejecuto o no una secuencia, no manejo niguna salida,  de esta manera me evito de hacer polling en la secuencia del programa sobre los botones de comando y ademas como condiciona el while siempre termina la secuencia completa, es frio el dialogo y tambien  no soy muy bueno explicando , je je no es lo mio la docencia,  no te hagas problemas si no entiendes es por mi culpa.

Mi ejemplo tambien muestra como puedes individualizar que entrada cambio de 0 a 1 conviertiendolo en un valor para realizar una opracion determinada que es la pregunta del inicio de este post.

En el caso que mencionas del motor de dos sentidos , ni cuando uso PLC dejo de enclavar a travez de contactos auxiliares NC las bobinas de los contactores pues es la unica manera de que no te explote todo por el aire por mas seguro que sea tu programa.

un saludo

Ariel


saludos
PikMan


 

anything