Autor Tema: Problema interrupción RB  (Leído 2114 veces)

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

Desconectado Pacio

  • PIC10
  • *
  • Mensajes: 8
Problema interrupción RB
« en: 04 de Marzo de 2016, 21:30:55 »
Hola foro que tal?
    Armo el post porque estoy teniendo problemas para utilizar la interrupción por cambio de estados rb4-rb7, llevo dias tratando de hacerla funcionar, ya me lei todos los post que encontre sobre este tema y no logro solucionarlo, el proyecto en el que estoy se basa en leer las salidas de un receptor de aeromodelismo , que basicamente son señales pwm, puedo leer perfectamente una salida, pero mi idea seria,por ahora poder leer 4,que es lo que deberia permitirme la int.RB, y si tienen alguna idea de como leer las 8 que me proporciona el receptor mejor :)

la situacion es la siguiente, logro leer el estado del pin rb4,detecto el estado en el que estaba antes y el actual por lo que detecto que cambio se produjo, la idea es que en el flanco de subida de la señal pwm pongo en 0 un contador, y en el flanco de bajada obtengo la cantidad de ticks que duro el estado alto, esto lo logro perfectamente, mi problema es que si quiero realizar el mismo procedimiento para rb5-6-7 no funciona! asi de simple, entra a la interrupcion pero no me detecta ningún cambio, llevo dias probando distintos metodos, incluso cambie de micro pensando que se habia algun problema con ese y nada! sigue igual, adjunto el codigo completo, el compilador es CCS, y no lo estoy simulando, lo estoy probando en el protoboard..

Código: C
  1. #include <16f877a.h>
  2. #fuses HS,NOWDT,PUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOPROTECT
  3. #use delay (clock=20000000)
  4. //#byte puerto_B = 0x06 // Identificador para el puerto B.
  5.  
  6. #use FAST_IO(a)
  7. #use FAST_IO(B)
  8. #use FAST_IO(c)
  9. #use FAST_IO(e)
  10. #priority RB,TIMER1
  11.  
  12.  
  13. #include <lcd_flex.c>
  14.  
  15. //**************************REGISTROS DEL MPU ***************************************************************
  16.  
  17. #define SERVO1 pin_c0
  18. #define SERVO2 pin_c1
  19.  
  20. int16 cont=0,timer1=0,timer2=0;
  21. unsigned int pos1=45,pos2=75;
  22.  
  23. int1 estado_act1=0,estado_ant1=0,estado_act2=0,estado_ant2=0;
  24. float tiempo=0,tiempo2=0;
  25.  
  26. //#define clearRB #ASM \ movf portb \ #ENDASM
  27.  
  28.  
  29. int ant_b=0x00;
  30.  
  31. #int_rb
  32.  
  33. void rb_isr() {
  34. int port_b=0;
  35. int changes=0;
  36.  
  37. port_b=input_b();
  38.  
  39.     changes = ant_b^port_b;
  40.   ant_b=port_b;
  41.  
  42. if(bit_test(changes,4)){
  43.         if(bit_test(ant_b,4)){
  44.              output_high(pin_a0);
  45.         }
  46.         if(!bit_test(ant_b,4)){
  47.              output_low(pin_a0);
  48.         }
  49.  
  50. }
  51.  
  52.  
  53. }
  54.  
  55. #int_timer0               //la interrupcion por timer0
  56. void timer0_isr(void)
  57. {
  58.  
  59.     if(cont==1){
  60.     output_high(SERVO1);
  61.     output_high(SERVO2);
  62.     }
  63.     else if(cont<1000){
  64.       if(pos1<cont){
  65.          output_low(SERVO1);
  66.         }
  67.       if(pos2<cont){
  68.          output_low(SERVO2);
  69.         }
  70.     }
  71.     else{
  72.     output_low(SERVO1);
  73.     output_low(SERVO2);
  74.     cont=0;
  75.     }
  76.     cont++;
  77.     timer1++;
  78.     timer2++;
  79.     set_timer0(218);      //cargo el timer0 para que desvorde en un 0.2ms (con 135 en vez de 131 para compensar)
  80. }
  81.  
  82.  
  83.  
  84.  
  85.  
  86. void main()
  87. {
  88. set_tris_a(0b00000110);
  89. set_tris_b(0x11111111);
  90. set_tris_c(0b10000000);
  91. set_tris_d(0b00000000);
  92. set_tris_e(0x00);
  93.  
  94. port_b_pullups(TRUE);
  95.    Setup_adc_ports(NO_ANALOGS);
  96.    
  97.    //-----------------------configuro el timer 0-----------------------        
  98.       setup_counters( rtcc_internal, rtcc_div_1  | rtcc_8_bit);   //configuro timer0 con prescaler 1:1
  99.       set_timer0(156);                                            //cargo el timer0 para que desborde en un 0,02ms
  100.  
  101. setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  102.  
  103.    enable_interrupts(int_timer0);                                 //activo el timer0
  104.    enable_interrupts(int_RB);
  105.    enable_interrupts(GLOBAL);
  106.  
  107.  
  108. delay_ms(100);
  109.  
  110. lcd_init();
  111.  
  112. lcd_putc("\fCONECCION AL\nRECEPTOR ");
  113.  
  114. output_b(0xf0);
  115.  
  116. while(TRUE)
  117. {
  118.  
  119.  
  120. //if(!input(pin_b7)){
  121. //output_low(SERVO1);
  122. //}
  123. //else
  124. //{output_high(SERVO1);}
  125.  
  126. printf(lcd_putc,"\fT1=%f\nT2=%f",tiempo,tiempo2);
  127.  
  128. //printf(lcd_putc,"\fB:%u",puerto_b);
  129. delay_ms(10);
  130. //output_toggle(pin_a0);
  131.  
  132.  
  133. }
  134. }


aca dejo la funcion real, de como yo supongo que deberia funcionar para medir el tiempo de cada entrada, el ejemplo que esta en el codigo de arriba es para mostrar que no logro detectar los cambios si uso el pin b5-b6-b7


Código: C
  1. #int_RB
  2. void rb_isr(){
  3.  
  4. puerto_b=input_b();
  5.  
  6. if(input(pin_b5)){
  7. output_high(pin_a0);
  8. }
  9. else{
  10. output_low(pin_a0);
  11. }
  12.  
  13. estado_act1=bit_test(puerto_b,4);          // SE LEE LA ENTRADA RB4
  14. //estado_act2=bit_test(puerto_b,7);          // SE LEE LA ENTRADA ACTUAL
  15.  
  16.      if(estado_act1&&!estado_ant1){            // DETECCION DEL PULSO DE SUBIDA
  17.      timer1=0;               //SE PONE EN CERO EL CONTADOR PARA INICIAR LA CUENTA                                
  18.      }
  19.                                        
  20.      if(estado_ant1&&!estado_act1){                  // DETECCION DEL PULSO DE BAJADA
  21.      tiempo=timer1*0.02;             // SE CALCULAN LOS MS
  22.      }
  23.  
  24. //     if(estado_act2&&!estado_ant2){            // DETECCION DEL PULSO DE SUBIDA
  25. //     timer2=0;                                 //SE PONE EN CERO EL CONTADOR PARA INICIAR LA CUENTA
  26. //     }
  27.                                        
  28. //     if(estado_ant2&&!estado_act2){                // DETECCION DEL PULSO DE BAJADA
  29. //     tiempo2=timer2*0.02;                  // SE CALCULAN LOS MS
  30. //     }
  31.  
  32. estado_ant1=estado_act1;
  33. estado_ant2=estado_act2;
  34.  
  35. clear_interrupt(int_RB);
  36.  
  37. }

pd: como ven para contar el tiempo transcurrido uso el timer 0 ya que lo uso ademas para controlar servos, Agradezco su ayuda.
un saludo
PACIO!
« Última modificación: 04 de Marzo de 2016, 21:34:45 por Pacio »

Desconectado Pacio

  • PIC10
  • *
  • Mensajes: 8
Re:Problema interrupción RB
« Respuesta #1 en: 04 de Marzo de 2016, 21:50:55 »
Perdón, hago una corrección, mi suposición estaba mal:

con el único cambio de estado que entra a la interrupcion es con el cambio de rb4, con el resto de los pines ni siquiera se entera la int.!


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema interrupción RB
« Respuesta #2 en: 05 de Marzo de 2016, 17:15:53 »
Estoy intentando entender que queres hacer, por lo cual todavia no vi el codigo. Estas intentando leer el duty de cada PWM que llega al PIC ?.

Si es asi, podrias indicar la frecuencia del PWM, y la frecuencia a la que estas usando el PIC?
Los flancos de bajada o subida del PWM siempre ocurren en el mismo momento ( de todos los PWM me refiero como si fueran sincronizados? )

Desconectado Pacio

  • PIC10
  • *
  • Mensajes: 8
Re:Problema interrupción RB
« Respuesta #3 en: 05 de Marzo de 2016, 21:56:31 »
Hola killerjc gracias por el interes!
 
Exactamente, la idea del proyecto es poder leer el duty de 4 entradas PWM ,su frecuencia es de 50hz y el duty varia entre 1 ms y 2 ms

El micro corre a 20mhz

Realmente no sé si el flanco de subida de todas las salidas son al mismo tiempo (están sincronizadas) lo voy a averiguar, aunque por el momento en el codigo principal solo quiero que un led se prende en el flanco de subida de esta entrada y se apague en el flanco de bajada, pero solo lo logro con el pin rb4, si en el codigo cambias la entrada tb4 por rb5 rb6 o rb7 la nterrupción no funciona, por más que le doy vueltas no le encuentro mucho sentido

Un saludo
PACIO!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema interrupción RB
« Respuesta #4 en: 05 de Marzo de 2016, 23:28:23 »
Me parece raro, por que a la interrupcion deberia entrar cuando cualquier entrada cambie de nivel, De Rb4 a Rb7. Proba un codigo mas simple:

Código: C
  1. #int_RB
  2. void rb_isr(){
  3.  
  4.    puerto_b=input_b();
  5.    output_toggle(PIN_A0);
  6.    clear_interrupt(int_RB);
  7.  
  8. }

Y usa RB5 un pulsador, obviamente le vas a tener que hacer un "antirebote" con un capacitor y una resistencia, para que funcione asi como esta ya que sino podria entrar varias veces a la interrupcion. Pero podrias ver que cambia el pin A0 ante un cambio de Rb4 a Rb7. Como para realmente probar que funciona.
« Última modificación: 06 de Marzo de 2016, 03:53:08 por KILLERJC »

Desconectado Pacio

  • PIC10
  • *
  • Mensajes: 8
Re:Problema interrupción RB
« Respuesta #5 en: 06 de Marzo de 2016, 21:39:46 »
Muchas gracias KILLERJC por ayudarme

Empece de 0 de vuelta con la interrupción e hice lo que me sugeriste y logre no solo hacer funcionar correctamente la interrupcion sino tambien lograr mi objetivo :)

La razón exacta por la que no me funcionaba no la descubri, pero creo que fue un conjunto de cosas debido a que si no seteaba las resistencias de pullup del puerto no me funcionaba, y ahora si, ademas creo que el prottoboard me jugo una mala pasada, en fin, lo importante es que funciona, acá abajo dejo el codigo funcionando para el que lo necesite, estoy leyendo 4 entradas pwm de un receptor de aeromodelismo y las muestro en el display, además hay una rutina que funciona con el timer 0 para controlar en este caso 2 servos, aunque la cantidad es casi ilimitada solo agregando las instrucciones que faltan..

Código: C
  1. #include <16f877a.h>
  2. #fuses HS,NOWDT,PUT,NOBROWNOUT,NOLVP,NOCPD,NODEBUG,NOPROTECT
  3. #use delay (clock=20000000)
  4.  
  5. #use FAST_IO(a)
  6. #use FAST_IO(B)
  7. #use FAST_IO(c)
  8. #use FAST_IO(e)
  9.  
  10. #priority timer1,RB
  11.  
  12. #include <lcd_flex.c>
  13.  
  14. //**************************REGISTROS DEL MPU ***************************************************************
  15.  
  16. #define SERVO1 pin_c0
  17. #define SERVO2 pin_c1
  18.  
  19.  
  20. float tiempo[4]={0,0,0,0};
  21. int SERVOS[4]={65,65,65,65};
  22.  
  23. int puerto_b=0;
  24. int1 estado_act1=0,estado_ant1=0,estado_act2=0,estado_ant2=0,estado_act3=0,estado_ant3=0,estado_act4=0,estado_ant4=0;
  25. int16 cont=0,T1[4],T2[4],TT[4];
  26.  
  27. const float periodo=0.0002;
  28.  
  29.  
  30.  
  31. #int_RB
  32. void rb_isr(){
  33.  
  34.    puerto_b=input_b();
  35.  
  36.  
  37. estado_act1=bit_test(puerto_b,4);    
  38. estado_act2=bit_test(puerto_b,5);  
  39. estado_act3=bit_test(puerto_b,6);        
  40. estado_act4=bit_test(puerto_b,7);  
  41.  
  42.  
  43.      if(estado_act1&&!estado_ant1){            // DETECCION DEL PULSO DE SUBIDA
  44.      T1[0]=get_timer1();
  45.       }
  46.                                        
  47.      if(estado_ant1&&!estado_act1){                  // DETECCION DEL PULSO DE BAJADA
  48.      T2[0]=get_timer1();
  49.       if(T1[0]<T2[0]){TT[0]=T2[0]-T1[0]; tiempo[0]=TT[0]*periodo;}
  50.      }
  51.  
  52.      if(estado_act2&&!estado_ant2){            // DETECCION DEL PULSO DE SUBIDA
  53.      T1[1]=get_timer1();    
  54.      }
  55.                                        
  56.      if(estado_ant2&&!estado_act2){                  // DETECCION DEL PULSO DE BAJADA
  57.      T2[1]=get_timer1();
  58.      if(T1[1]<T2[1]){TT[1]=T2[1]-T1[1]; tiempo[1]=TT[1]*periodo;}
  59.      }
  60.  
  61.      if(estado_act3&&!estado_ant3){            // DETECCION DEL PULSO DE SUBIDA
  62.      T1[2]=get_timer1();  
  63.      }
  64.                                        
  65.      if(estado_ant3&&!estado_act3){                  // DETECCION DEL PULSO DE BAJADA
  66.      T2[2]=get_timer1();
  67.      if(T1[2]<T2[2]){TT[2]=T2[2]-T1[2]; tiempo[2]=TT[2]*periodo;}
  68.      }
  69.      
  70.      if(estado_act4&&!estado_ant4){            // DETECCION DEL PULSO DE SUBIDA
  71.      T1[3]=get_timer1();  
  72.      }
  73.                                        
  74.      if(estado_ant4&&!estado_act4){                  // DETECCION DEL PULSO DE BAJADA
  75.      T2[3]=get_timer1();
  76.      if(T1[3]<T2[3]){TT[3]=T2[3]-T1[3]; tiempo[3]=TT[3]*periodo;}
  77.      }
  78.  
  79. estado_ant1=estado_act1;
  80. estado_ant2=estado_act2;
  81. estado_ant3=estado_act3;
  82. estado_ant4=estado_act4;
  83.  
  84.    output_toggle(PIN_A0);
  85.    clear_interrupt(int_RB);
  86. }
  87.  
  88.  
  89. #int_timer0               //la interrupcion por timer0
  90. void timer0_isr(void)
  91. {
  92.  
  93.  
  94.  
  95.     if(cont==1){
  96.     output_high(SERVO1);
  97.     output_high(SERVO2);
  98.     }
  99.     else if(cont<1000){
  100.       if(SERVOS[0]<cont){
  101.          output_low(SERVO1);
  102.         }
  103.       if(SERVOS[1]<cont){
  104.          output_low(SERVO2);
  105.         }
  106.     }
  107.     else{
  108.     output_low(SERVO1);
  109.     output_low(SERVO2);
  110.     cont=0;
  111.     }
  112.     cont++;
  113.   set_timer0(156);
  114.  
  115. }
  116.  
  117.  
  118. void main()
  119. {
  120. set_tris_a(0b00000000);
  121. set_tris_b(0xf0);    
  122. set_tris_c(0b11100000);
  123. set_tris_d(0b00000000);
  124. set_tris_e(0x00);
  125.  
  126.  
  127. //++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ //
  128. //++++++++++++++ ++++++++++++++ ++++++++  CONFIGURACION TIMERS ++++++++++++++ ++++++++++++++ ++++++++++++++ //
  129. //++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ ++++++++++++++ //
  130.       setup_counters( rtcc_internal, rtcc_div_1  | rtcc_8_bit);   //configuro timer0 con prescaler 1:1
  131.       set_timer0(156);                                            //cargo el timer0 para que desborde en un 0,02ms
  132.  
  133. setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  134.  
  135.  enable_interrupts(int_timer0);                                 //activo el timer0
  136.  enable_interrupts(int_RB);
  137.  enable_interrupts(GLOBAL);
  138.  
  139. delay_ms(100);
  140.  
  141. lcd_init();
  142.  
  143. lcd_putc("\fPrueba int RB");
  144. delay_ms(500);
  145.  
  146. while(TRUE)
  147. {
  148.  
  149. //SERVOS[0]=35+(((tiempo[2]*100)-100)/2);
  150.  
  151. printf(lcd_putc,"\fT1=%f  T2=%f\nT3=%f  T4=%f",tiempo[0],tiempo[1],tiempo[2],tiempo[3]);
  152.  
  153. output_toggle(pin_a1);
  154. delay_ms(40);
  155.  
  156. }
  157. }

Tanto las lecturas como los movimientos del servos son bastante estables, aunque no del todo

Si alguien tiene ideas para optimizar el código,o un método distinto para lograr mayor estabilidad les voy a estar muy agradecido que lo compartan, como así ideas para poder leer mayor cantidad de entradas que las que me limita la interrupción RB

De nuevo muchas gracias
Un saludo
PACIO!