desktop

Problemas con interrupcion

Amigos una vez mas recurro a ustedes y sus conocimientos, tengo el siguiente problema:

- Tengo un programa que lee el encoder de un motor, el software lleva la cuenta del encoder y la muestra por un display lcd, a su vez activa ciertas puertas al momento de llegar a cierto punto de la cuenta. El encoder se lee por RB0 y RB1, hasta ahi va todo de perillas, a continuacion les muestro el codigo.

Código:
#Include    <18F452.h>
#Fuses      XT, NOWDT, NOPROTECT, NOLVP, BROWNOUT
#use        Delay(Clock = 4000000)
#include    <LCD.c>


#use fast_io(A)                  // configura como deben ser tratado los  registros TRIS
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)

#Byte PortA = 0xF80
#Byte PortB = 0xF81            
#Byte PortC = 0xF82            
#Byte PortD = 0xF83 

void led (void);
void led1(void);
void led2(void);


// ------ Variable Global ------

int16 cont=3000; 
int   temp  = 0;                  // Esta variable ha de ser global porque su valor lo
int   flag_temp;
int   reset; 
                                // Por tanto declaramos esta variable antes la interrupción
                                 // y de "void main".



Void Main(){                     // Inicio y configuración.
   
   lcd_init();
   Port_B_Pullups(FALSE);        // Configuración para el PIC 18F452.
   Setup_ADC_Ports(NO_ANALOGS);  // Sin comparadores ni ADCs, todo digital, etc...
   Setup_adc(ADC_CLOCK_DIV_2);
   Setup_spi(SPI_SS_DISABLED);
   Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   Setup_timer_2(T2_DISABLED,0,1);
   set_timer1(3036);
   
   
  
    
   Enable_Interrupts(Int_Ext);  // Activar Interrupción Externa a través de RB0. 
   Ext_Int_Edge(L_TO_H);        // Inicialmente detectar interrupción por flanco de subida
   enable_interrupts(INT_TIMER1);
   Enable_Interrupts(GLOBAL);   // Interrupciones Generales Activadas. 

   set_tris_A(0b00000000);
   set_tris_B(0b11111111);
   set_tris_C(0b00000000);
   
   output_A(0);
   output_C(0);
   
   

   // ---------- Programa Principial ----------
        
   While (True){

     
      lcd_gotoxy(5,1);
      printf(LCD_PUTC, "Posicion");
      lcd_gotoxy(7,2);
      printf(LCD_PUTC, "%Ld",cont);
      
    
      while((cont>3003)&&(cont<=3150)){              
 
            lcd_gotoxy(5,1);
            printf(LCD_PUTC, "Posicion");
            lcd_gotoxy(7,2);
            printf(LCD_PUTC, "%Ld",cont);
            led();
      }
      
      bit_clear(PORTC,0);
      flag_temp = 1;
      if ((cont<=2995)&&(cont>=2870)&&(flag_temp==1)){
      
            enable_interrupts(INT_TIMER1);
      }
      
      //inicia temporizador 10seg por interrupcion (definir un flag_temp que de cero cuando se cumplan 10 segundos)
      
      while((cont<2995)&&(cont>=2865)&&(flag_temp==1)){
            
            lcd_gotoxy(5,1);
            printf(LCD_PUTC, "Posicion");
            lcd_gotoxy(7,2);
            printf(LCD_PUTC, "%Ld",cont);
            bit_set(PORTA,1);
            delay_ms(100);
            bit_set(PORTA,0);
            led1();
      }
      
      disable_interrupts(INT_TIMER1);
      output_low(PIN_C1);
      
      while((cont<=2995)&&(cont>=2870)&&(flag_temp==0)){
         
            lcd_gotoxy(5,1);
            printf(LCD_PUTC, "Posicion");
            lcd_gotoxy(7,2);
            printf(LCD_PUTC, "%Ld",cont); //ver posicion de encoder por LCD 
            bit_clear(PORTA,1);//saco alimentacion
            delay_ms(100);
            reset=1;
            led2();
      }
      
      output_low(PIN_C2);
      
      if((cont>=2997)&&(cont<=3000)&&(reset==1)){
            bit_clear(PORTA,0);//reestablesco el sentido de giro
            delay_ms(200);
            cont=3000;
            reset=0;
             
      }  
   }
}


#int_TIMER1
void  TIMER1_isr(void) {
 
   temp++;
   
   if (temp >= 20){
      flag_temp=0;
      temp=0;
   }
   set_timer1(3036);
}


#INT_EXT                        // Interrupción Externa por RB0: Decodificación de Encoder.
Void IntRB0() 
{
                                // CCS se encarga de desactiva automáticamente cualquier interrupción.
                                // No hace falta guardar contextos de registros.

   If (Bit_Test(PortB, 0))      // Si RB0 se ha puesto a 1 (flanco de subida),
   {  
       Ext_Int_Edge(H_TO_L);    // entonces activar la siguiente interrupción por flanco de
                                // bajada. 
       If (Bit_Test(PortB, 1))  // Si RB1 está a 1,
       {
         
           cont++;              // entonces incrementar una unidad el valor de cont.
          
       }
   }
   Else                         // Si RB0 se ha puesto a 0 (flanco de bajada),
   {  
       Ext_Int_Edge(L_TO_H);    // entonces activar la siguiente interrupción por flanco de
                                // subida.
       If (Bit_Test(PortB, 1))  // Si RB1 está 1,
       {
         
           cont--;              // entonces decrementar una unidad el valor de cont.
           
       }
   }
}

void led(){
delay_ms(100);
output_toggle(PIN_C0);
}

void led1(){

output_toggle(PIN_C1);

}

void led2(){
output_toggle(PIN_C2);

}


esto lo he probado en protoboard y anda todo muy bien, de hecho mejor de lo que esperaba :LOL:

El problema que tengo aparece cuando agrego una nueva interrupcion externa, esta se hace por RB2 y esta configurada H_to_L, lo he probado en proteus y funciona pero al grabarla en el micro y llevarlo al proto no anda, el micro simplemente no prende, no se enciende el display y no enciende los led piltos que tengo configurados, a continuacion les dejo el codigo con la interrupcion RB2 agregada

Código:
#Include    <18F452.h>
#Fuses      XT, NOWDT, NOPROTECT, NOLVP, BROWNOUT
#use        Delay(Clock = 4000000)
#include    <LCD.c>


#use fast_io(A)                  // configura como deben ser tratado los  registros TRIS
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)

#Byte PortA = 0xF80
#Byte PortB = 0xF81            
#Byte PortC = 0xF82            
#Byte PortD = 0xF83     


// ------ Variable Global ------
int16 cont=3000;                
int   temp  = 0;                  // Esta variable ha de ser global porque su valor lo
int   flag_temp;
int   reset;                     // usaremos en la interrupción y en el programa principal.
int   boton=0;
int   comprobacion;                                 // Por tanto declaramos esta variable antes la interrupción
                                 // y de "void main".
void led (void);
void led1(void);
void led2(void);
void emergencia (void);


Void Main(){                     // Inicio y configuración.
   
   lcd_init();
   Port_B_Pullups(FALSE);        // Configuración para el PIC 18F452.
   Setup_ADC_Ports(NO_ANALOGS);  // Sin comparadores ni ADCs, todo digital, etc...
   Setup_adc(ADC_CLOCK_DIV_2);
   Setup_spi(SPI_SS_DISABLED);
   Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   Setup_timer_2(T2_DISABLED,0,1);
   set_timer1(3036);
   
   enable_interrupts(INT_RB);
   Enable_Interrupts(INT_EXT);  // Activar Interrupción Externa a través de RB0. 
   Ext_Int_Edge(L_TO_H);        // Inicialmente detectar interrupción por flanco de subida.
   enable_interrupts(INT_EXT2_H2L );
   Enable_Interrupts(GLOBAL);   // Interrupciones Generales Activadas. 

   set_tris_A(0b00000000);
   set_tris_B(0b11111111);
   set_tris_C(0b00000000);
   
   output_A(0);
   output_C(0);
   
   // ---------- Programa Principial ----------
        
   While (True){

      lcd_gotoxy(5,1);
      printf(LCD_PUTC, "Posicion");
      lcd_gotoxy(7,2);
      printf(LCD_PUTC, "%Ld",cont);
      
    
      while((cont>3003)&&(cont<=3150)){              
 
            lcd_gotoxy(5,1);
            printf(LCD_PUTC, "Posicion");
            lcd_gotoxy(7,2);
            printf(LCD_PUTC, "%Ld",cont);
            led();
      }
      
      bit_clear(PORTC,0);
      flag_temp = 1;
      if ((cont<=2995)&&(cont>=2870)&&(flag_temp==1)){
      
            enable_interrupts(INT_TIMER1);
      }
      
      //inicia temporizador 10seg por interrupcion (definir un flag_temp que de cero cuando se cumplan 10 segundos)
      
      while((cont<2995)&&(cont>=2865)&&(flag_temp==1)){
            
            lcd_gotoxy(5,1);
            printf(LCD_PUTC, "Posicion");
            lcd_gotoxy(7,2);
            printf(LCD_PUTC, "%Ld",cont);
            bit_set(PORTA,1);
            delay_ms(100);
            bit_set(PORTA,0);
            led1();
      }
      
      disable_interrupts(INT_TIMER1);
      output_low(PIN_C1);
      
      while((cont<=2995)&&(cont>=2870)&&(flag_temp==0)){
         
            lcd_gotoxy(5,1);
            printf(LCD_PUTC, "Posicion");
            lcd_gotoxy(7,2);
            printf(LCD_PUTC, "%Ld",cont); //ver posicion de encoder por LCD 
            bit_clear(PORTA,1);//saco alimentacion
            delay_ms(100);
            reset=1;
            led2();
      }
      
      output_low(PIN_C3);
      
      if((cont>=2997)&&(cont<=3000)&&(reset==1)){
            bit_clear(PORTA,0);//reestablesco el sentido de giro
            delay_ms(200);
            cont=3000;
            reset=0;
             
      }  
   }
}


// --------- Interrupción ---------

#int_ext2 

void RB2 (){

output_low(PIN_A0);
output_low(PIN_A1);

while((Bit_Test(PortB, 2)==0)&&(boton<=100)){

boton++;
}
comprobacion=1;
while ((Bit_Test(PortB, 2)==0)&&(comprobacion==1)&&(Bit_Test(PortB, 3)==0)){

      output_low(PIN_C0);
      output_low(PIN_C1);
      output_low(PIN_C3);
      bit_set(PORTC,3);
      emergencia();
      
      
}

while ((Bit_Test(PortB, 2)==0)&&(comprobacion==1)&&(Bit_Test(PortB, 3)==1)){

if((Bit_Test(PortB, 4)==1)){

bit_clear(PORTA,2);

}
output_high(PIN_A2);   
}
bit_clear(PORTC,4);
bit_clear(PORTC,2);
comprobacion=0;
boton=0;
   }
#int_TIMER1
void  TIMER1_isr(void) {
 
   temp++;
   
   if (temp >= 20){
      flag_temp=0;
      temp=0;
   }
   set_timer1(3036);
}



#INT_EXT                        // Interrupción Externa por RB0: Decodificación de Encoder.
Void IntRB0() 
{
                                // CCS se encarga de desactiva automáticamente cualquier interrupción.
                                // No hace falta guardar contextos de registros.

   If (Bit_Test(PortB, 0))      // Si RB0 se ha puesto a 1 (flanco de subida),
   {  
       Ext_Int_Edge(H_TO_L);    // entonces activar la siguiente interrupción por flanco de
                                // bajada. 
       If (Bit_Test(PortB, 1))  // Si RB1 está a 1,
       {
         
           cont++;              // entonces incrementar una unidad el valor de cont.
          
       }
   }
   Else                         // Si RB0 se ha puesto a 0 (flanco de bajada),
   {  
       Ext_Int_Edge(L_TO_H);    // entonces activar la siguiente interrupción por flanco de
                                // subida.
       If (Bit_Test(PortB, 1))  // Si RB1 está 1,
       {
         
           cont--;              // entonces decrementar una unidad el valor de cont.
           
       }
   }
}


  /*Al finalizar la interrupción CCS se encarga de volver a poner automáticamente
  la badera INTF = 0 ---> borra la interrupción para poder permitir la siguiente;
  no hemos de hacer nada por nuestra parte.*/


      
void led(){
delay_ms(100);
output_toggle(PIN_C0);
}

void led1(){

output_toggle(PIN_C1);

}

void led2(){
output_toggle(PIN_C2);

}
  
void emergencia(void){

//bit_set(PORTC,4);
bit_set(PORTA,0);
bit_set(PORTA,1);

}



Descarte problemas de conexion ya que solo hay que agregar una entrada mas y eso anda bien, la verdad ya no se que hacer, ojala me puedan ayudar, saludos y gracias desde ya.
 
Creo que la interrupción dura demasiado... ¿Has medido cuánto puede ser? A lo mejor se produce una segunda interrupción mientras no ha terminado de procesarse la primera.
 
Última edición por un moderador:
En una línea tienes

enable_interrupts(INT_RB);

pero luego, en la interrupción RB2, tienes

#int_ext2

¿Eso es correcto?
 
Acabo de solucionar el problema y era precisamente eso, una mendiga linea de codigo y no andaba nada :LOL:, muchas gracias por tu ayuda, ahora respiro tranquilo :LOL:
 
Atrás
Arriba