Autor Tema: Problema para salir de una interrupcion INT_RB  (Leído 1965 veces)

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

Desconectado ASABoomer

  • PIC10
  • *
  • Mensajes: 12
Problema para salir de una interrupcion INT_RB
« en: 21 de Abril de 2015, 01:41:49 »
Saludos se que este tema ha sido muy tocado en este foro, pero he intentado varios métodos para poder salir de la interrupción y me vuelva a la función principal de mi programa, e intentado usar una variable auxiliar para leer y sobrescribir el puerto b y también he tratado e limpiar el registro RBIF dentro de la misma interrupción, y por ahora estoy intentando leer  sobrescribir el puerto b con asm, pero no tengo éxito, una vez que hago la interrupción por el puerto b el programa ya no sale de ahí, este es parte de mi código, :


#include <16F873a.h>
 #FUSES XT,NOWDT,NOPROTECT,NOPUT
 #use delay(clock=4000000)
         
 int16 distanciaf, tiempof;
 int16 distanciat, tiempot;
 int16 distanciad, tiempod;
 int16 distanciai, tiempoi;
 
 #define disparof PIN_C0
 #define disparot PIN_C1
 #define disparod PIN_C2
 #define disparoi PIN_C3
 #define ecof PIN_C4
 #define ecot PIN_C5
 #define ecod PIN_C6
 #define ecoi PIN_C7

 #BYTE TRIS_A = 0X85
 #BYTE PORT_A = 0X05
 #BYTE TRIS_B = 0X86
 #BYTE PORT_B = 0X06
 #BYTE TRIS_C = 0X87
 #BYTE PORT_C = 0X07


#INT_RB
void CAMBIO_B(void){

#asm movf PORT_B,0 #endasm   
   
   if(PORT_B==0b00010000)
    {
       output_A(0b111010);
       delay_ms(1500);
    }
 
   if(PORT_B==0b00100000){
      output_A(0b110101);
         delay_ms(1500);
   }         
   
   if(PORT_B==0b01000000){
      output_A(0b111001);
      delay_ms(1500);
   }         
   
   if(PORT_B==0b10000000){
      output_A(0b110110);
      delay_ms(1500);
   }   
}


 void main()
 {
 setup_adc_ports(NO_ANALOGS);

 enable_interrupts(INT_RB);
 enable_interrupts(GLOBAL);
 
 set_tris_A(0x00);
 set_tris_B(0xF0);
 set_tris_C(0b11110000);
 
 PORT_A=0;
 PORT_B=0b11110000;
 PORT_C=0;

 delay_ms(5000);
 output_A(0b110101);
 delay_ms(4500);
 output_A(0x00);           

 while(1)
{
//............
}
ESTOY LISTO!!... Y TU?!?!?!........

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #1 en: 21 de Abril de 2015, 02:41:20 »
Ya con el    if(PORT_B==0b00010000) estarias leyendo el puerto asi que no veo necesidad de poner una funcion en ASM,.

Probaste al final de la interrupcion borrar el bit INTCON.RBIF ?, Recien cuando lo lees te permite el cambio del mismo.

Ademas otro problema Es MUY mala idea poner un delay() dentro de una rutina de interrupcion, si se produce otro cambio en alguno de los RB esto va a significar que se vuelva a activar la condicion de interrupcion por ende la necesidad de leer el puerto y volver a borrar el FLAG. Ademas de ser una mala practica y perder la nocion de lo que es una interrupcion.

Desconectado ASABoomer

  • PIC10
  • *
  • Mensajes: 12
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #2 en: 21 de Abril de 2015, 03:24:24 »
Saludos KILLERJC antes que nada gracias por leer.

Si al terminar los if de la función de interrupción añadi un clear interrupt(INT_RB); y también he probado desactivando la interrupción RB y luego las globales, incluso ya he cambiado un poco la función


#INT_RB
void RB_isr(void){
   
   if(input(PIN_B4)==1)
    {
       output_A(0b111010);
       delay_ms(1500);
    }
 
   if(input(PIN_B5)==1){
      output_A(0b110101);
         delay_ms(1500);
   }         
   
   if(input(PIN_B6)==1){
      output_A(0b111001);
      delay_ms(1500);
   }         
   
   if(input(PIN_B7)==1){
      output_A(0b110110);
      delay_ms(1500);
   }
 clear_interrupt(INT_RB);    
}

quizá sea por los delay, como es para el control de motores los considere necesarios hare una prueba sin ellos
ESTOY LISTO!!... Y TU?!?!?!........

Desconectado ASABoomer

  • PIC10
  • *
  • Mensajes: 12
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #3 en: 21 de Abril de 2015, 03:41:37 »
He quitado los delay, pero sigo sin tener éxito una vez entrando a la interrupción ya no regresa al programa principal, he intentado haciendo un switch case pero el resultado es el mismo 
ESTOY LISTO!!... Y TU?!?!?!........

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #4 en: 21 de Abril de 2015, 04:12:34 »
Mirando al final suelen hacer:

 output_b(input_b());


Desconectado ASABoomer

  • PIC10
  • *
  • Mensajes: 12
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #5 en: 21 de Abril de 2015, 04:45:26 »
Intente ponerlo antes de limpiar el RBIF, pero sin tener éxito quizá sea mi circuito que por no tener el sensor ultrasónico en la librería de PROTEUS no se interpreta de la manera mas adecuada en el simulador, donde C0 a C3 son los disparos del sensor ultrasónico y C4 a C7 son los ecos del sensor, únicamente le puse los pulsos para que haga la medición y como están siempre tendrá como tiempo mas pequeño C4 que hara que los motores vayan asia el frente los dos, al hacer la interrupción en B0 la dirección cambia asia atrás, al probar el programa sin interrupción y varias los pulsos de pines hace el cambio en los motores muy bien y sin ningún problema, haciendo las interrupciones por separado igual anda bien, pero al hacerlo con la función y el programa principal al poner la interrupción cualquiera en 1, jala bien pero al regresar a 0 no regresa a la función principal ya solo puedo hacer los cambios a través del puerto B


#INT_RB
void RB_isr(void){


   if(input(PIN_B4)==1)
    {
       output_A(0b111010);
       //delay_ms(1500);
    }
 
   if(input(PIN_B5)==1){
      output_A(0b110101);
         //delay_ms(1500);
   }         
   
   if(input(PIN_B6)==1){
      output_A(0b111001);
      //delay_ms(1500);
   }         
   
   if(input(PIN_B7)==1){
      output_A(0b110110);
      //delay_ms(1500);
 
}
 output_b(input_b());
 clear_interrupt(INT_RB);
}
ESTOY LISTO!!... Y TU?!?!?!........

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #6 en: 21 de Abril de 2015, 05:17:24 »
Bueno yo veo mal las resistencias de 100 ohms pero esto lleva a que no puedas tener esto: output_b(input_b());, asi que primero quitar lo que te dije de poner y quitar esas resistencias de 100ohms
ya que el CCS solo te los cambia a salida al estar en standart_io, y deberias usar un #fast_io(b), pero intentemos omitir eso xD

Lo que veo en todos lados:
Código: C
  1. #INT_RB
  2. void rb_isr(){
  3.       unsigned int8 valor=input_B(); //Traemos el valor del puerto B
  4.       valor=valor & 0b01110000; //Enmascaramos el estado de pines que no sean B5, B6 o B7
  5.       switch(valor){
  6.             case 0b01000000: //En caso de estar pulsada solamente B7. Equivalente a case 64
  7.                   //Llamas a una funcion que actue por presionar B7
  8.                   break;
  9.             case 0b00100000: //En caso de estar pulsada solamente B6. Equivalente a case 32
  10.                   //Llamas a una funcion que actue por presionar B6
  11.                   break;
  12.             case 0b00010000: //En caso de estar pulsada solamente B5. Equivalente a case 16
  13.                   //Llamas a una funcion que actue por presionar B5
  14.                   break;
  15.             default: //En caso de estar pulsadas mas de una tecla a la vez
  16.                   //Hacer algo o no hacer nada :P
  17.       }
  18. }

Codigo asi hay por todos lados, no limpian el flag, solamente leen. Y les anda. Usa un switch case pero aun asi es el mismo codigo :/
Eso si quita los delays

Desconectado ASABoomer

  • PIC10
  • *
  • Mensajes: 12
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #7 en: 21 de Abril de 2015, 11:36:11 »
Esa parte del dipswitch lo copie de otro circuito ya que se me hizo mas cómodo activar las interrupciones así en la simulación, ya que en realidad la activación de la interrupción es a través de sensores optoelectricos. Ya había empleado el #use fast_io(B); quitando los delay al hacer el build de los archivos me a quitado el warning 216 de la finalización de las interrupciones al final del programa, y solo me queda el de que siempre esta activo un while. Desde el principio mi compilación tuvo problemas para la lectura de mis sensores ultra sónicos al poner cada sensor como función y llamarla en el programa principal me trajo muchos problemas por lo que tuve que ponerlo todo en el programa principal. Lo de los sensores ultrasoonicos se que miden con la implementación que hice de los pulsos ya uqe probe la medición de los cuatro al mismo tiempo con el display LCD, pero adjunto todo el código por si algo esta mal ahí y no permite que retorne al programa principal al apagar todos los pines del puerto B:

ESTOY LISTO!!... Y TU?!?!?!........

Desconectado ASABoomer

  • PIC10
  • *
  • Mensajes: 12
Re: Problema para salir de una interrupcion INT_RB
« Respuesta #8 en: 21 de Abril de 2015, 11:38:54 »
Jeje disculpa lo puse para descarga para evitar cosa de que creean que tenga virus lo dejamos aquí también:

#include <16F873a.h>
 #FUSES XT,NOWDT,NOPROTECT,NOPUT
 #use delay(clock=4000000)
         
 int16 distanciaf, tiempof;
 int16 distanciat, tiempot;
 int16 distanciad, tiempod;
 int16 distanciai, tiempoi;
 
 #define disparof PIN_C0
 #define disparot PIN_C1
 #define disparod PIN_C2
 #define disparoi PIN_C3
 #define ecof PIN_C4
 #define ecot PIN_C5
 #define ecod PIN_C6
 #define ecoi PIN_C7

 #BYTE TRIS_A = 0X85
 #BYTE PORT_A = 0X05
 #BYTE TRIS_B = 0X86
 #BYTE PORT_B = 0X06
 #BYTE TRIS_C = 0X87
 #BYTE PORT_C = 0X07
 #use fast_io(B)

#INT_RB
void RB_isr(){
   unsigned int8 valor=input_B();
   valor=valor&0b11110000;
   switch(valor){
      case 0b00010000:
           output_A(0b111010);
          break;
 
      case 0b00100000:
         output_A(0b110101);
            break;
      
      case 0b01000000:
         output_A(0b111001);
         break;         
   
      case 0b10000000:
         output_A(0b110110);
         break;
       default:
          break;
}
 clear_interrupt(INT_RB);
}


 void main()
 {
 setup_adc_ports(NO_ANALOGS);
 clear_interrupt(INT_RB);
 enable_interrupts(INT_RB);
 enable_interrupts(GLOBAL);
 set_tris_A(0x00);
 set_tris_B(0xF0);
 set_tris_C(0b11110000);
 
 PORT_A=0;
 PORT_B=0;
 PORT_C=0;



 delay_ms(5000);
 output_A(0b110101);
 delay_ms(4500);
         

 while(1)
 {
lectura:
 setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);   
 
 //Sensor adelante
 output_high(disparof);                   
 delay_us(20);                       
 output_low(disparof);
 while(!input(ecof))                     
 {
 set_timer1(0);
 }                       
 while(input(ecof))                     
 {
 tiempof=get_timer1();
 distanciaf=(tiempof*10)/(58.0);
 delay_ms(50);
 break;
 }
 
 //Sensor atras
 output_high(disparot);                   
 delay_us(20);                       
 output_low(disparot);
 while(!input(ecot))                     
 {
 set_timer1(0);
 }                         
 while(input(ecot))                     
 {
 tiempot=get_timer1();
 distanciat=(tiempot*10)/(58.0);
 delay_ms(50);
 break;
 }
 
 //Sensor derecho
 output_high(disparod);                   
 delay_us(20);                       
 output_low(disparod);
 while(!input(ecod))                     
 {
 set_timer1(0);
 }                         
 while(input(ecod))                     
 {
 tiempod=get_timer1();
 distanciad=(tiempod*10)/(58.0);
 delay_ms(50);
 break;
 }
 
 //Sensor izquierdo
 output_high(disparoi);                   
 delay_us(20);                       
 output_low(disparoi);
 while(!input(ecoi))                     
 {
 set_timer1(0);
 }                         
 while(input(ecoi))                     
 {
 tiempoi=get_timer1();
 distanciai=(tiempoi*10)/(58.0);
 delay_ms(50);
 break;
 }
   
 if(distanciaf>50 && distanciat>50 && distanciad>50 && distanciai>50){ // si lectura > 50cm entonces no es valida
    goto lectura;
   }
 else{ // si distancia fue < 50cm es una distancia valida
      if(distanciaf<distanciat && distanciaf<distanciad && distanciaf<distanciai){
         output_A(0b110101);
         goto lectura;
      }
     
      if(distanciat<distanciaf && distanciat<distanciad && distanciat<distanciai){
         output_A(0b111010);
         goto lectura;
      }   
     
      if(distanciad<distanciaf && distanciad<distanciat && distanciad<distanciai){
         output_A(0b111001);
         goto lectura;
      }
     
     if(distanciai<distanciaf && distanciai<distanciat && distanciai<distanciad){
         output_A(0b110110);
         goto lectura;
      }
 }
 }
 }
ESTOY LISTO!!... Y TU?!?!?!........


 

anything