Autor Tema: Comenzando con interrupcion RB0  (Leído 2721 veces)

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

Desconectado ramirez

  • PIC16
  • ***
  • Mensajes: 195
Comenzando con interrupcion RB0
« en: 28 de Junio de 2009, 14:59:49 »
Hola a todos de nuevo, después de bastante tiempo viendio ejemplos por el foro, e intentar ver su funcionamiento, he hecho un ejemplo, pero este no funciona. Lo que intento hacer es que después de pulsar un pulsador en RB0/INT (conectado entre aquí y masa),se endienda un led conectado en RA0 durante 500 ms. Pero no logra funcinar ¿qué ocurre?.

Otra pregunta que quiero hacer es la siguiente: ¿el programa solo ejecuta el programa principal, y se queda parado en el bucle final, y se irá a "void interupcion_externa (void)", sólo cuando se active la interrupción? ¿se irá de nuevo al programa principal cuando se haya ejecutado todo "void interupcion_externa (void)".

El programa es el siguiente:

#include <16F84a.H>
#fuses HS,NOWDT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)



// DEFINICION DE INTERUPCION EXTERNA
#int_ext
void interupcion_externa (void)
{

output_high(PIN_A0);   
      delay_ms(500);
output_low(PIN_A0);
     
/* PROGRAMACION DE LAS RUTINAS DE ATENCION A LA INTERRUPCION EXTERNA */
}

// PROGRAMA PRINCIPAL

void main (void)
{
//configuracion de puertos
SET_TRIS_A(0x04); // PUERTO A COMO SALIDA
SET_TRIS_B(0X03); // PUERTO B COMO ENTRADA
output_low(PIN_A0);

// HABILITACION DE INTERUPCIONES EXTERNAS Y GLOBAL
ext_int_edge(L_TO_H); // interrupcion para comparacion flanco de subida
enable_interrupts(int_ext); // habilitacion de interupcion externa
enable_interrupts(global);
while (true)
            {/* PROGRAMA PRINCIPAL */}
}


De nuevo gracias por vuestra colaboración.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con interrupcion RB0
« Respuesta #1 en: 28 de Junio de 2009, 17:04:21 »
Estas definiendo cristal HS cuando en realidad debería ser XT.

Despues tienes que tener en cuenta que hay dos formas de trabajar con los puertos:
#use standard_io(puerto)
     Cada vez que se utiliza el puerto o el pin del puerto, se genera código adicional para establecerlo como entrada o salida según sea el caso. En este caso usar set_tris_X no es necesario.
#use fast_io(puerto)
     En este caso al escribir o leer un puerto o pin no genera el código adicional para establecer su tris, por ello se debe configurar el puerto previamente con set_tris_X.

En tu caso setear los tris no tienen sentido, porque por default el compilador lo trata de standard.

Otra pregunta que quiero hacer es la siguiente: ¿el programa solo ejecuta el programa principal, y se queda parado en el bucle final, y se irá a "void interupcion_externa (void)", sólo cuando se active la interrupción? ¿se irá de nuevo al programa principal cuando se haya ejecutado todo "void interupcion_externa (void)".

Aquí hay una explicación de que se tratan las interrupciones. Solo hay que agregar que CCS realiza el guardado y restablecimiento de W, STATUS y PC  automáticamente, aparte de borrar las banderas de las interrupciones.

     
No contesto mensajes privados, las consultas en el foro

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Comenzando con interrupcion RB0
« Respuesta #2 en: 29 de Junio de 2009, 00:08:37 »
ese retardo de medio segundo dentro de la interrupción no es buena idea hacerlo, en tu lugar yo lo haría así:

Código: [Seleccionar]
...
int1 bUsar_RA0

#int_ext
void interupcion_externa (void)
{
 bUsar_RA0=1;
     
/* PROGRAMACION DE LAS RUTINAS DE ATENCION A LA INTERRUPCION EXTERNA */
}

// PROGRAMA PRINCIPAL

void main (void)
{
//configuracion de puertos
SET_TRIS_A(0x04); // PUERTO A COMO SALIDA
SET_TRIS_B(0X03); // PUERTO B COMO ENTRADA
output_low(PIN_A0);

// HABILITACION DE INTERUPCIONES EXTERNAS Y GLOBAL
ext_int_edge(L_TO_H); // interrupcion para comparacion flanco de subida
enable_interrupts(int_ext); // habilitacion de interupcion externa
enable_interrupts(global);
while (true)
            {
...
if(bUsar_RA0){

output_high(PIN_A0);   
delay_ms(500);
output_low(PIN_A0);
bUsar_RA0=0;
}
...

/* PROGRAMA PRINCIPAL */}
}

y si nos ponemos mas quisquilloso con el programa :), yo haría el retardo por interrupción del timer, el cual haría el programa mas eficiente.

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado ramirez

  • PIC16
  • ***
  • Mensajes: 195
Re: Comenzando con interrupcion RB0
« Respuesta #3 en: 29 de Junio de 2009, 12:03:23 »
Hola de nuevo, sigo sin poder hacer funcionar la interrupción la última versión que tengo es:

#include <16F84a.H>
#fuses XT,NOWDT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use standard_io(A)
#use standard_io(B)


// DEFINICION DE INTERUPCION EXTERNA
#int_ext
void interupcion_externa (void)
{

output_high(PIN_A0);  
delay_ms(500);
output_low(PIN_A0);
      
/* PROGRAMACION DE LAS RUTINAS DE ATENCION A LA INTERRUPCION EXTERNA */
}

// PROGRAMA PRINCIPAL

void main (void)
{
do{

// HABILITACION DE INTERUPCIONES EXTERNAS Y GLOBAL
output_high(PIN_A0);
ext_int_edge(L_TO_H); // interrupcion para comparacion flanco de subida
enable_interrupts(int_ext); // habilitacion de interupcion externa
enable_interrupts(global);
}while (true);
          
}

Otra cosa, en el ejemplo dado por nuestro amigo PalitroqueZ, no lo veo con claridad, además que significa "int1 bUsar_RA0".

Gracias de nuevo
« Última modificación: 29 de Junio de 2009, 12:27:56 por ramirez »

Desconectado ramirez

  • PIC16
  • ***
  • Mensajes: 195
Re: Comenzando con interrupcion RB0
« Respuesta #4 en: 29 de Junio de 2009, 12:51:44 »
Me he dado cuenta de que sobtra una línea, "output_high(PIN_A0); ", del progrma principal, si quito esta línea funciona correctamente, pero eso sí debo de tener un tren de pulsos en RB0, pero si este tren de pulsos lo sustituyo por un pulsador mendiante un divisor de tensión, ya no funciona, el divisor de tensión está compuesto por resiostencias de 420 omhios y 100k obteniendo en RB0 tenisones de 1,65 voltios y 4,99 voltios. ¿porqué no funciona el divisor de tensión? ¿la estructura del programa está bien?

Otra vez gracias

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con interrupcion RB0
« Respuesta #5 en: 29 de Junio de 2009, 13:08:17 »
El 0 lógico tiene que estar entre 0 y 0.2 volts.
No contesto mensajes privados, las consultas en el foro

Desconectado ramirez

  • PIC16
  • ***
  • Mensajes: 195
Re: Comenzando con interrupcion RB0
« Respuesta #6 en: 29 de Junio de 2009, 13:17:37 »
ok. He cambiado el divisor de tensión por una resistencia en serie con el pulsador, y en el punto intermendio hacia RB0, y funcina correctamente. ¿la forma de hacer la interrupción es correcta? Pero está más de 500 ms el led en estado alto.


Gracias
« Última modificación: 30 de Junio de 2009, 03:46:05 por ramirez »

Desconectado ramirez

  • PIC16
  • ***
  • Mensajes: 195
Re: Comenzando con interrupcion RB0
« Respuesta #7 en: 05 de Julio de 2009, 14:52:58 »
Hola de nuevo, sigo en el intento de que la interrupción funcione correctamente, ahora lo que he hecho ha sido cambiar el interruptor por un tren de pulsos de 1 Hz, como lo podeis ver en la imagen adjunta, pero he puesto que después de la interrupción RA0 esté en estado alto durante 100 ms y como podéis ver en la imagen del osciloscopio dura 400 ms.
He visto varios ejemplos en el foro y tengo la misma estructura, el programa definitivo que he utilizado es el siguiente:

#include <16F84a.H>
#fuses XT,NOWDT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)
#use standard_io(A)
#use standard_io(b)
#use fixed_io(a_outputs=PIN_A0,PIN_A1)

// DEFINICION DE INTERUPCION EXTERNA
#int_ext
void IntRB0()
{
output_low(PIN_A0);
output_high(PIN_A0);
delay_ms(100);
output_low(PIN_A0);

}

// PROGRAMA PRINCIPAL

void main (void)
{

// HABILITACION DE INTERUPCIONES EXTERNAS Y GLOBAL

ext_int_edge(L_TO_H); // interrupcion para comparacion flanco de subida
enable_interrupts(int_ext); // habilitacion de interupcion externa
enable_interrupts(global);
for(;;){}

}

¿porque a la hora de ejecutase el programa, siempre esta en el último for, esperando una interrupción por RB0, y  una vez que haq ocurrido la interrupción se ejecuta esta parte del programa?

#int_ext
void IntRB0()
{
output_low(PIN_A0);
output_high(PIN_A0);
delay_ms(100);
output_low(PIN_A0);

}


Creo que es así como funciona esta interrupción, pero sigo sin saber que pasa con los 400 ms, ¿tendrá algo que ver con el relon?
De nuevo gracias por vuestra colaboración

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Comenzando con interrupcion RB0
« Respuesta #8 en: 05 de Julio de 2009, 15:03:52 »
Veo que no tienen ni idea que es una interrupción! Lee el link que te di anteriormente para saber como funcionan las interrupciones en un PIC. Aquí hay algo mas sobre interrupciones.

Después el problema de que no se cumplen los tiempos, me parece que esta mal configurado el reloj del PIC en Proteus, revisa eso.
No contesto mensajes privados, las consultas en el foro