Autor Tema: Interrupcion en CCS.  (Leído 1610 veces)

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

Desconectado Ranculche

  • PIC12
  • **
  • Mensajes: 74
Interrupcion en CCS.
« en: 04 de Diciembre de 2014, 15:15:16 »
Hola a todos, de nuevo estoy aquí para molestar, no es una buena semana. Resulta que estoy con un programita para medir el ancho de un pulso de entrada, para lo cual uso la interrupcion RB0, cuando tengo un flanco de subida, pongo el timer1 en 0 y cambio la configuracion de la interrupcion para flanco de bajada, asi cuando el pulso caiga, leo el timer1 y obtengo las cuentas. El problema que tengo es que el Micro no se porque razon no me deja hacer otra cosa, como que se cuelga, pero no deja de medir el ancho del pulso. Cuando desabilito las interrupciones globales, empieza a funcionar el resto del programa, pero no puedo medir. He probado desactivar las interrupciones globales entre las lineas de programa, pero queda colgado tambien. Seguro es algo simple, pero no puedo solucionarlo. Talves algún fuse, o alguna configuración de interrupciones. A continuacion dejo el programa. Muchas gracias de antemano.

Código: [Seleccionar]
//------Directivas para el compilador--------

#Include <16F886.h>                                                             //PIC utilizado
#Fuses HS, NOWDT, NOPUT, NOBROWNOUT, NOCPD, NOPROTECT                   //Configuramos los fuses
#Use Delay (Clock=20000000)                                                            //Oscilador a 4Mhz
#Use Fast_Io(B)                                                                       //Optimizamos E/S del PORTB
#Use Fast_Io(A)                                                                 //Optimizamos E/S del PORTA
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#byte portb = 0x06


long Pulsos=0;
long Pulsos_ant=0;
long Pulsos_act=0;
int i=0;
int j=1;
int Activo=0;

void main(void)
{


//-----------------------configuramos la interrupciones------------------------------------------
disable_interrupts(global);                              //desactivo todas las interrupciones

//-----------------------configuro el timer 1--------------------------------------------------
setup_timer_1( T1_INTERNAL | T1_DIV_BY_1);    //Defino como fente al clock interno
  set_timer1(0);                                          //cargo el timer0
enable_interrupts(INT_TIMER1);

//-----------------------configuro la Interrupcion Externa------------------------------------
enable_interrupts(INT_EXT);
ext_int_edge(L_TO_H);


//---------------------------//activo las interrupciones---------------------------------------


enable_interrupts(global);

set_tris_a(0b00001111);
set_tris_b(0b00000011);
set_tris_c(0b10001111); 
 
output_high(PIN_C5);
delay_ms(1000);
output_low(PIN_C5);
   
Pulsos_ant=Pulsos;


while(true)
{
delay_ms(1000);
Pulsos_act=Pulsos;
disable_interrupts(global);
if(Pulsos_act<(Pulsos_ant-200))
{
Activo=1;
output_high(PIN_C5);
}
if(Pulsos_act>(Pulsos_ant+200))
{
Activo=0;
output_low(PIN_C5);
}
Pulsos_ant=Pulsos_act;
if(Activo==1)
{
printf("Y\n\r");
}
else
{
printf("N\n\r");
}
delay_ms(10);
enable_interrupts(global);
}
   
}


#int_ext
void Interrupcion_ext()
{
if(input(PIN_B0))
{
set_timer1(0);
ext_int_edge( H_TO_L );
}
else
{
Pulsos=get_timer1();
ext_int_edge( L_TO_H );
}
}

Saludos.-

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Interrupcion en CCS.
« Respuesta #1 en: 04 de Diciembre de 2014, 15:44:37 »
1-
Si medis el ancho de pulso solo te interesa las interrupciones externas y no las del TMR ( a no ser que sean MUY largo el pulso, y tuvieras que contar los overflow del mismo, pero en tu codigo no lo veo previsto/programado a eso )

enable_interrupts(INT_TIMER1);

Asi que eso estaria de mas. A no ser que apliques lo que acabo de mencionar.

2-
No podes desabilitar la interrupcion en medio del programa como aca

   while(true)
   {   
      delay_ms(1000);   
      Pulsos_act=Pulsos;
      disable_interrupts(global);

Imaginate que esta la señal, viene el flanco positivo, entra a tu interrupcion cambias a flanco negativo , entra en el while y desactiva las interrupciones globales, el flanco negativo pasa (activando la bandera), cuando actives de nuevo las interrupciones, disparara la interrupcion haciendo que la lectura sea incorrecta, ya que no sabes en que parte desde que desactivaste la interrupcion termino ese pulso.

Tambien ese delay de 1 seg. Imaginate tambien que pasan pulsos mientras esta ese delay, en ejemplo seria que te den los timers durante ese delay 100 300 500 700 500 100, pero como viste el primero y el ultimo al "calcular" el tiempo pensas que estaban iguales. Este delay puede usarse si no te interesa que pase "en el medio".

3-
Creo que lo que queres hacer es:

Interrupcion ()
{
Flanco de subida ? SI : cambio a flanco de bajada y TMR = 0
NO: desabilito interrupciones, limpio flag, cambio flanco a subida, muestro, activo interrupciones de nuevo
}

Es decir, realizas la toma de datos y luego mostras con interrupcion desabilitada, pero dejas de tomar datos mientras envias/mostras tu resultado. Esto te va a limitar entre la proximidad de pulsos en alto que tengas.
Ademas con tu programa vas a tener que cambiar bastante el ancho de pulso entre el primero y el segundo para que se modifiquen las salidas. Es mala practica realizar un programa dentro de la rutina de interrupcion, por lo tanto deberias de asignar un flag para que en tu programa principal muestre o no los resultados.

La otra es que dejes como esta y con otro TMR uses la interrupcion para que  cuando ocurra el overflow del mismo desabilitas las entradas y mostras si es que hubo algun cambio o no. Aca vas a tener que pensar que pueden existir mas de 2 pulsos en juego por lo que vas a tener que pensar en otra forma de mostrarlo o  interpretarlo. Pero esta en el mismo caso que tenes vos con tu codigo y el tema del delay.

4-
Tambien podes eliminar una variable o 2 sin sentido

Citar
      if(Pulsos_act<(Pulsos_ant-200))
      {   
         output_high(PIN_C5);
         printf("Y\n\r");
      }
      if(Pulsos_act>(Pulsos_ant+200))
      {   
         output_low(PIN_C5);
         printf("N\n\r");      
      }
      Pulsos_ant=Pulsos_act;
      

Al igual que en la rutina de interrupcion, cambias por
Pulsos_act=get_timer1();

Y eliminas :

Pulsos_act=Pulsos;

Y No usas mas la variable Pulsos. Pero eso es gusto nomas xD, si te resulta mas facil pensarlo con 3 variables adelante.

Con respecto que tu programa quede colgado es por ese delay, o por el diaparo de la interrupcion del timer0. Otra no se me ocurre.
« Última modificación: 04 de Diciembre de 2014, 17:58:14 por KILLERJC »


 

anything