Autor Tema: Interrupciones externas se inician solas al principio!  (Leído 3338 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado zafra_bcn

  • PIC10
  • *
  • Mensajes: 3
Interrupciones externas se inician solas al principio!
« en: 18 de Junio de 2010, 08:54:37 »
Hola!!
Somos una pareja de estudiantes de Barcelona que estamos realizando nuestro proyecto final de carrera... lo tenemos todo más o menos controlado excepto una cosa que no entendemos... y quizá alguno de vosotros nos podría decir algo al respeto.
Cada vez que conectamos el PIC18F4620, se ejecutan (por orden 0, 1 y 2) las tres interrupcciones que conforman nuestro programa... Y eso no lo queremos. Queremos que cuando se ejecuten no al iniciar, si no cuando se produzcan por medio de tres botones conectados a masa.
Además en los pines RB3 a RB7 tenemos conectados LED's para visualizar el estado del PIC... y el LED en el RB5 no se nos enciende nunca... y lo hemos probado todo, incluso con otro PIC por si ese estuviera mal.

Os dejamos sencillo programa que, segun ejecuta interrupciones, enciende LED's... (el global es más complicado... pero es que esto tan sencillo hace lo que quiere al principio... y lo del LED del RB5 es algo inexplicable...)

Si alguien nos puede ayudar...
Muchas gracias! Saludos desde Barcelona!!!


#include <18F4620.h>
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOPROTECT                //Code not protected from reading
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES LVP                      //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled
#FUSES HS                       //High Speed Oscilator

#use delay(clock=40000000)

#use standard_io(B)
#use standard_io(C)
#use standard_io(E)


#INT_EXT2                        //Directiva de la interrupción.
void visualizar_inversor()       //Rutina visualización valor actual.
{
     delay_ms(1000);              //Retardo para evitar el rebote.
     output_high(PIN_B4);        //Encender LED medida actual.
     delay_ms(10000);
     output_low(PIN_B4);
}

#INT_EXT                         //Directiva de la interrupción EXT0.

void funcion_int_ext()           //Rutina de la interrupción.
{
      delay_ms(1000);             //Retardo para evitar el rebote.
      output_high(PIN_B6);       //Enciende el LED de medida.
      delay_ms(10000);           //Retardo de la conexión del relé.
      output_low(PIN_B6);
}


#INT_EXT1                        //Directiva de la interrupción.
void transmision()               //Rutina de la interrupción de transmisión.
{

      delay_ms(1000);
      output_high(PIN_B5);       //Encender LED transmisión.           
      delay_ms(10000);
      output_low(PIN_B5);        //Apagar LED transmisión.
}

void main()                      //Programa principal.
{
   port_b_pullups(TRUE);         //Habilitación de las resistencias de Pull-up.
   disable_interrupts(GLOBAL);
   enable_interrupts(int_ext);      //Habilita interrupcion del boton de medida.
   enable_interrupts(int_ext1);     //Habilita la interrupción de transmisión.
   enable_interrupts(int_ext2);     //Hailita la interrupción de valor actual.
   ext_int_edge(H_TO_L);            //Por flanco de bajada.
   enable_interrupts(GLOBAL);       //Habilita las interrupciones globales.
   setup_timer_0(RTCC_INTERNAL);       //Configuración Timer 0.
   
   output_high(PIN_B7);    //Encender LED ON-OFF.
   output_low(PIN_B6);     //Apaga el resto de LEDS.
   output_low(PIN_B5);
   output_low(PIN_B4);

 while (1)                 //Realizar siempre.
    {
    }
}

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Interrupciones externas se inician solas al principio!
« Respuesta #1 en: 18 de Junio de 2010, 09:19:32 »
creo que el problema esta en que no defines los vectores de inicio del programa, ni de las interrupciones.
Y un tema es tambien el de incorporar delays dentro de las rutinas de interrupción, piensa que las interrupciones son para atender eventos que no quieres perderte, asi que si tienes un delay de 1 seg dentro de la interrupcion, el programa se queda clavado en esa tarea.
Los retardos es mejor hacerlos por interrupciones de cualquiera de los TMR.
Código: [Seleccionar]
/** V E C T O R  R E M A P P I N G *******************************************/

extern void _startup (void);        // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
    _asm goto _startup _endasm
}
#pragma code

#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
    ;
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
    ;
}
#pragma code

/** D E C L A R A T I O N S **************************************************/
#pragma code
/******************************************************************************
 * Function:        void main(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Main program entry point.
 *
 * Note:            None
 *****************************************************************************/
void main(void)
{
}

Eso es para el 18F4550, tendria que ver si para el  18F4620 los vectores son esos mismo.
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado pablomanieri

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 639
Re: Interrupciones externas se inician solas al principio!
« Respuesta #2 en: 18 de Junio de 2010, 09:34:27 »
Te recomiendo que antes de activar las interrupciones borres los flags correspondientes a las interrupciones que vas a activar y luego activarlas, ya que cuando pic inicia, hay flags de interrupciones que se activan.
El pin B5 no enciende porque tienes activado el #fuses LVP, y este usa el pin B5 para entrar al modo de programación, cuando lo configuras como Low Voltage Prog.
« Última modificación: 18 de Junio de 2010, 09:40:38 por pablomanieri »

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Interrupciones externas se inician solas al principio!
« Respuesta #3 en: 18 de Junio de 2010, 11:15:26 »
willynovi el compilador que usa es CCS  :mrgreen:


La solución está seguramente en lo que comenta pablomanieri   ;-)


Saludos!

No contesto mensajes privados, las consultas en el foro

Desconectado willynovi

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 546
Re: Interrupciones externas se inician solas al principio!
« Respuesta #4 en: 18 de Junio de 2010, 11:29:06 »
aja puede ser por eso que no le anda entonces, deberias pasarte al C18  :mrgreen:

Ademas de inicializar las flag, cuando atiendes una interrupción antes de salir de ella deberias nuevamente borrar la flag correspondiente a esa interrupción, ya que sino cuando retornas al programa principal se te ejecutará la interrupción.

Y ya que estamos pregunto, qué en el CCS no es necesario hacer el mapeo de los vectores? :shock:

Saludos,
Intento enseñarte a pescar, si solo quieres pescados, espera que un pescador te regale los suyos.

Desconectado zafra_bcn

  • PIC10
  • *
  • Mensajes: 3
Re: Interrupciones externas se inician solas al principio!
« Respuesta #5 en: 18 de Junio de 2010, 19:27:14 »
Muchas gracias!!!!!!!!!
El lunes lo provaré sin falta y os cuento!!!!
Espero que funcione!!!!

De verdad, muchas gracias!!!!!
Saludos!

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Interrupciones externas se inician solas al principio!
« Respuesta #6 en: 18 de Junio de 2010, 22:15:04 »
Hola zafra_bcn. No soy experto en CCS, pero he estado mirando tu código y veo algunas lineas que te pueden estar causando problemas.

El CCS no es un lenguage de programación totalmente ANSI standard, por lo que resulta muy cómodo para principiantes como nosotros.  Lo mejor para implementar código en CCS entonces es estudiar un poco las instrucciones que vamos a utilizar en el manual y asi verás como no tienes que preocuparte por manejar flags ni estar observando el estado de registros ni bits ni nada de esas cosas que se parecen tanto al lenguaje ensamblador, ya que es el mismo CCS quien internamente hace todas estas operaciones por nosostros.

De entrada para tu código te recomiendo la siguiente configuración:

Código: [Seleccionar]
#include <18F4620.h>
// #device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV21                   //Brownout reset at 2.1V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES MCLR                     //Master Clear pin enabled

#use delay(clock=40000000)

Como podrás ver, he cambiado un par de fuses (LVP por NOLVP y PBADEN por NOPBADEN).  Revisa muy bien la hoja de datos del PIC respecto a estos dos fuses y de acuerdo a tu circuito y a tu programador.

También te recomiendo el siguiente encabezado para el main:

Código: [Seleccionar]
void main()
{
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2|ADC_TAD_MUL_0);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_OFF);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT1);
   enable_interrupts(INT_EXT2);
   enable_interrupts(GLOBAL);

Por experiencia, en CCS es mejor curarse en salud y desactivar todo lo que no se va a usar.

Citar
Cada vez que conectamos el PIC18F4620, se ejecutan (por orden 0, 1 y 2) las tres interrupcciones que conforman nuestro programa... Y eso no lo queremos. Queremos que cuando se ejecuten no al iniciar, si no cuando se produzcan por medio de tres botones conectados a masa.

Respecto a esto y por algunas experiencias que podrás ver aquí en el foro con el uso de la instrucción port_b_pullups(TRUE), te recomendaría que si tus pulsadores van conectados al negativo, mejor les coloques resistencias 'pull-up' a cada pin de unos 10K ya que sin estas el ruido te puede activar aleatoriamente los pines y es muy posible que sea por eso que las interrupciones se inician solas.

Finalmente, veo que en el código de las interrupciones tienes insertados unos delays de 1 segundo y otro de 10 segundos al encender y apagar cada LED.  No es muy recomendable meter tiempos excesivos como estos dentro de una interrupción, sino que más bien lo que debe uno hacer dentro de la interrupción es crear una condición lógica para que el código principal del programa la interprete y ejecute lo que deseamos.

Bueno, les deseo mucha suerte con su proyecto.  Un saludo,

Bernardo
« Última modificación: 19 de Junio de 2010, 09:00:59 por bmb »

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Interrupciones externas se inician solas al principio!
« Respuesta #7 en: 19 de Junio de 2010, 02:18:17 »
A mí esos delays dentro de las interrupciones me ponen nervioso.

De todas formas, no veo que hayas definido los pines de las interrupciones externas como entradas. Habría que hacer un set_tris_....

Desconectado bmb

  • PIC18
  • ****
  • Mensajes: 423
Re: Interrupciones externas se inician solas al principio!
« Respuesta #8 en: 19 de Junio de 2010, 08:59:41 »
El pin B5 no enciende porque tienes activado el #fuses LVP, y este usa el pin B5 para entrar al modo de programación, cuando lo configuras como Low Voltage Prog.

Hola, veo que ya pablomanieri te había advertido sobre el uso de este fuse; disculpa, no había leido con atención.

A mí esos delays dentro de las interrupciones me ponen nervioso.

De todas formas, no veo que hayas definido los pines de las interrupciones externas como entradas. Habría que hacer un set_tris_....

También se me habia pasado por alto, como bien te dice Nocturno, el uso de la instrucción set_tris...

Un saludo
« Última modificación: 19 de Junio de 2010, 11:07:22 por bmb »

Desconectado zafra_bcn

  • PIC10
  • *
  • Mensajes: 3
Re: Interrupciones externas se inician solas al principio!
« Respuesta #9 en: 21 de Junio de 2010, 14:34:24 »
Muchas gracias!
Con todo lo aportado hemos conseguido que no haga cosas "raras" y encienda el LED!
Ahora nos falta alguna cosilla más que esperamos solucionar en los próximos días.
El programa es mucho más complejo que el que escribimos aquí, hay conversiones, tablas, CCP1, Timers, etc.... pero parece que funciona, si tenemos alguna consulta más abriremos un nuevo tema en el foro!

Muchas, muchas gracias!!!!!!
Atentamente,