Autor Tema: problema con timer1  (Leído 3303 veces)

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

Desconectado perry

  • PIC10
  • *
  • Mensajes: 12
problema con timer1
« en: 02 de Marzo de 2007, 07:28:56 »
Hollllaaaaaa!!!!!!!

Estoy haciendo un programa que recibe pulsos por RB0, utilizando el timer1 y visualizo la frecuencia por un lcd. Os pego el programa:

#include <18f4550.h>

#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,BROWNOUT,NOPBADEN,NOLVP,NOCPD,DEBUG

#use delay(clock=20000000)

#use fast_io(B)
#include "lcd.c"

float const uSxTick = 0.2;       // Microsegundos por Tick de TMR1 a 20 Mhz

///////////////////////////////////////////////////////////////////////////
//                    variables a guardar                                //
///////////////////////////////////////////////////////////////////////////

long t1;
long tt;
float st1;
float st_tot_overflow;
float f;
float f_final;
int  n_overflow;
long  t_tot_overflow;
long alarma_max=150;
long alarma_min=0;

long frecuencia();


/////////////////////////////////////////////////////////////////////////
//
// Interrupción por externa por cambio de flanco en RB0 //
//
/////////////////////////////////////////////////////////////////////////

#int_ext

void handle_ext_int()
   {
      t1=get_timer1();
      set_timer1(0);
      n_overflow=0;
      output_high (PIN_A0);
         delay_ms(200);
         output_low (PIN_A0);
   }

#int_timer1

void overflow()
   {
      ++n_overflow;
         
               
   }

void main ()
{

   




/////////////////////////////////////////////////inicializaciones generales///
   delay_ms(333); // Espero a que todo se estabilice e ...
  disable_interrupts(global); // Inicializo el Micro y ...
  disable_interrupts(int_timer1); // deshabilitando todo lo no necesario ...
  disable_interrupts(int_rda);
  disable_interrupts(int_ext);
  disable_interrupts(int_ext1);
  disable_interrupts(int_ext2);
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_OFF);
  setup_spi(FALSE);
  setup_psp(PSP_DISABLED);
  setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  setup_timer_0(RTCC_OFF);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_timer_3(T3_DISABLED);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
  port_b_pullups(FALSE);
  delay_ms(333);
/////////////////////////////////////////////////////////////////////////



set_tris_b(0xFF);


lcd_init();
Delay_ms(1000);

lcd_putc("\f");   
lcd_putc("   pulsometro \n");
   Delay_ms (1000);
 

ext_int_edge(0,L_to_H);


 
enable_interrupts(int_ext);           // Habilito las interrupciones necesarias
enable_interrupts(int_timer1);
clear_interrupt(int_ext);
clear_interrupt(int_timer1);
enable_interrupts(global);

while (true)
{

   
      
      
      lcd_putc("\f");
      lcd_gotoxy (2,10);
      printf(lcd_putc,"%5.2f \n",f_final);
      delay_ms (1000);
         
      
   

      }   
}


      
      


   
////////////////////////////////////////////////////////////////////////////////
//
// funciones
//
////////////////////////////////////////////////////////////////////////////////////

long frecuencia ()
   {
   st1 = uSxTick * t1;            // calculo el tiempo en microsegundos
   t_tot_overflow = (((2^16)-1) * n_overflow);      // ticks de todos los overflow
   st_tot_overflow = (t_tot_overflow * uSxTick);   //tiempo overflows
   tt = st_tot_overflow + st1;         //tiempo total
   f = 1 / (tt * 1000000);         // frecuencia
   f_final = f * 60;
   
   return (f_final);
   }


La interrupción del salto salta porque el led de A1 se enciende cada vez que llega un pulso pero no consigo visualizar en el display el tiempo, ya que sólo veo 0.00.

He estado mirando unos ejemplos de la pagina de redpic pero no encuentro el fallo que tengo. ¿me podeis echar un cable?

muchas gracias. No sabeis lo que me está ayudando este foro para ir haciendo mis programillas porque hace unas semanas no sabía ni lo que era el c :-/

Desconectado perry

  • PIC10
  • *
  • Mensajes: 12
Re: problema con timer1
« Respuesta #1 en: 02 de Marzo de 2007, 07:34:38 »
Me he olvidado d llamar a la funcion frecuencia pero aún así no consigo ver nada


#include <18f4550.h>

#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,BROWNOUT,NOPBADEN,NOLVP,NOCPD,DEBUG

#use delay(clock=20000000)

#use fast_io(B)
#include "lcd.c"

float const uSxTick = 0.2;       // Microsegundos por Tick de TMR1 a 20 Mhz

///////////////////////////////////////////////////////////////////////////
//                    variables a guardar                                //
///////////////////////////////////////////////////////////////////////////

long t1;
long tt;
float st1;
float st_tot_overflow;
float f;
float f_final;
int  n_overflow;
long  t_tot_overflow;
long alarma_max=150;
long alarma_min=0;

long frecuencia();

/////////////////////////////////////////////////////////////////////////
//
// Interrupción por externa por cambio de flanco en RB0 //
//
/////////////////////////////////////////////////////////////////////////

#int_ext

void handle_ext_int()
   {
      t1=get_timer1();
      set_timer1(0);
      n_overflow=0;
      output_high (PIN_A0);
         delay_ms(200);
         output_low (PIN_A0);
   }

#int_timer1

void overflow()
   {
      ++n_overflow;
         
               
   }

void main ()
{

   




/////////////////////////////////////////////////inicializaciones generales///
   delay_ms(333); // Espero a que todo se estabilice e ...
  disable_interrupts(global); // Inicializo el Micro y ...
  disable_interrupts(int_timer1); // deshabilitando todo lo no necesario ...
  disable_interrupts(int_rda);
  disable_interrupts(int_ext);
  disable_interrupts(int_ext1);
  disable_interrupts(int_ext2);
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_OFF);
  setup_spi(FALSE);
  setup_psp(PSP_DISABLED);
  setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
  setup_timer_0(RTCC_OFF);
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
  setup_timer_2(T2_DISABLED,0,1);
  setup_timer_3(T3_DISABLED);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
  port_b_pullups(FALSE);
  delay_ms(333);
/////////////////////////////////////////////////////////////////////////



set_tris_b(0xFF);


lcd_init();
Delay_ms(1000);

lcd_putc("\f");   
lcd_putc("   pulsometro \n");
   Delay_ms (1000);
 

ext_int_edge(0,L_to_H);


 
enable_interrupts(int_ext);           // Habilito las interrupciones necesarias
enable_interrupts(int_timer1);
clear_interrupt(int_ext);
clear_interrupt(int_timer1);
enable_interrupts(global);

while (true)
{
lcd_putc("\f");   
   
      
      frecuencia();
      lcd_putc("\f");
      lcd_gotoxy (2,10);
      printf(lcd_putc,"%5.2f \n",f_final);
      delay_ms (1000);
      }   
}


      
      


   
////////////////////////////////////////////////////////////////////////////////
//
// funciones
//
////////////////////////////////////////////////////////////////////////////////////

long frecuencia ()
   {
   st1 = uSxTick * t1;                        // calculo el tiempo en microsegundos
   t_tot_overflow = (((2^16)-1) * n_overflow);      // ticks de todos los overflow
   st_tot_overflow = (t_tot_overflow * uSxTick);   //tiempo overflows
   tt = st_tot_overflow + st1;                  //tiempo total
   f = 1 / (tt * 1000000);                     // frecuencia
   f_final = f * 60;
   
   return (f_final);
   }

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: problema con timer1
« Respuesta #2 en: 04 de Marzo de 2007, 16:00:33 »
Prueba a quitar el delay_ms(200) de la función de interrupción de RB0. Para hacer el efecto de encender y apagar el led puedes usar el timer0 y así evitas usar delays en medio de una interrupción.

Saludos!!

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: problema con timer1
« Respuesta #3 en: 05 de Marzo de 2007, 12:23:05 »
Me parece que estás tratando de hacer un frecuencímetro. Si esa es tu aplicación creo que lo mejor será que utilices los contadores del uC, en el foro hay información de como hacer un frecuencímetro.

El uso de INT/EXT te puede servir pero si esa es tu aplicación no me parece la solución más lógica.

Un saludo Reinier

Desconectado ALE1973

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 230
Re: problema con timer1
« Respuesta #4 en: 06 de Marzo de 2007, 11:06:21 »
Buenas... Aprovechando el post de perry, aprovecho para hacer una consulta sobre el timer1, la aplicacion es simple, con un pic16f873, programado en ccs, a 4 mhz.

El programa (que luego escribo), espera una interrupcion externa a travez de rb0, en ese momento pone a cero el timer1, luego en el main(), lee el timer1, y lo compara con el resultado de una conversion AD de 10 bits, cuando el timer1 es igual o mayor al valor de la conversion AD, se ejecuta algo, hasta aca todo bien, el problema es que cuando hago esto, teniendo constante el valor del AD, el timer1 no se dispara siempre en el mismo valor...

Cual es la idea... simplemente comparar 2 valores de 16bits, uno generado por el AD (10bits) y otro generado por el timer1, esto me da un pulso del ancho que yo quiera (regulado por el AD).

Lo raro de esto es que si hago exactamente lo mismo, pero con el timer0 y el ad a 8 bits, si funciona a la perfeccion.
Les dejo el codigo.. y desde ya gracias.

Alejandro.


#include <16f873.h>                          // Definiciones del PIC 16F873
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT  //
#use delay(clock=4000000)                     // Oscilador a 4 Mhz


#pragma use fast_io(A)
#pragma use fast_io(B)
#pragma use fast_io(C)

//    PINES   /////////////////////////////////////////////////////////////////
#define pLed1     PIN_A1
#define pLed2     PIN_A2
#define pLed3     PIN_A3
#define pLed4     PIN_A4

#define pSensor1  PIN_B7                 //sensor de botella 1
#define pSensor2  PIN_B6                 //sensor de botella 2
#define pContactor   PIN_B5
#define pTanque   PIN_B4
#define pPico2    PIN_B3
#define pPico1    PIN_B2
#define pMang2    PIN_B1
#define pMang1    PIN_B0

#define pEV1      PIN_C4                 //Electrovalvula botella 1
#define pEV2      PIN_C5                 //Electrovalvula botella 1

#define pE_lcd    PIN_D0                 //sensor de botella 2



// VARIABLES EN RAM ///////////////////////////////////////////////////////////

int1 f1_seg;                           // Flag de un segundo
int1 fcruce0;
int  rTimer1;                          // Tiempo de encendido V1
int  rTemp;                        
int  rPulsos;                          //
int  rTimeOff_V2;                      //
int1 prevIn1;                          //
int1 prevIn2;                          //
INT  rDelay;                           //
int  rLeds;                            // Imagen de los leds



// Declaración de Funciones ///////////////////////////////////////////////////


// INTERRUPCIONES /////////////////////////////////////////////////////////////


}
#int_RTCC
void RTCC_isr() {                      // Interrupción Timer 0
   rDelay++;


}

#int_TIMER1
void T1_isr() {                      // Interrupción Timer 1
      IF(input(PIN_B7))
      output_low(PIN_B7);
   ELSE
      OUTPUT_HIGH(PIN_B7);


}

#INT_EXT
void ext_isr(){
     if(input(PIN_B0)){
         ext_int_edge(H_TO_L);
         fcruce0=1;
     }
     ELSE{
         ext_int_edge(L_TO_H);
         fcruce0=1;
     }
     set_timer1(0);
}


#INT_TIMER2                            //Interrupcion por timer 2
void TIMER2_isr() {                    //cada 1ms para control de tiempo
}


// Desarrollo de Funciones ////////////////////////////////////////////////////





//,,,,,,,,,,,,Programa Principal /////////////////////////////////////////////////////////

void main() {

//++++++++++++++++++Configura puertos analogicos++++++++++++++++++++++++++++++
   setup_adc(  ADC_CLOCK_INTERNAL  );
   setup_adc_ports( RA0_ANALOG );                 // Ver que puertos van a ser analogicos
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   setup_timer_1(T1_INTERNAL|T1_DIV_8);

   set_tris_a (0b00000011);
   set_tris_b (0b00000001);
   set_tris_c (0b11000000);
   rDelay = 0;
   rLeds  = 1;


   ext_int_edge(H_TO_L);         //selecciono interrupcion por flanco descendente
   //enable_interrupts(int_RTCC);                  // Habilita Interrupción TIMER0
   enable_interrupts(int_ext);                   // Habilita Interrupción RB0

  //enable_interrupts(int_TIMER1);                // Habilita Interrupción TIMER1
  // enable_interrupts(int_TIMER2);                // Habilita Interrupción TIMER2
   enable_interrupts(global);                    // Habilita interrupciones

   output_b(0);

   do {

      rTimer1=get_timer1();
       
      if(fcruce0){                               // Si hay disparo pendiente
         if(rTimer1>=rTemp){
         fcruce0=0;
         do {
         output_high(PIN_C4);
         delay_us(10);
         output_low(PIN_C4);
         delay_us(10);
         }while(rPulsos++<20);
         rPulsos=0;
         rTemp=read_adc();
        }
      }

   } while (TRUE);

}

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18310
    • MicroPIC
Re: problema con timer1
« Respuesta #5 en: 11 de Marzo de 2007, 06:24:19 »
Yo quitaría de la interrupción externa ese delay_ms(200) que lo único que hace es impedir que se recoja el siguiente pulso.

Para calcular la frecuencia estás dividiendo por 1.000.000 que imagino será una estimación del tiempo que tarda tu aplicación en volver a calcularla, por el delay_ms del bucle principal. Creo que es un método bastante inexacto; te recomiendo utilizar un segundo timer para establecer los periodos de recuento.

No obstante, creo que la mejor forma de hacer el frecuencímetro es otra, utilizando sólo dos timers y no la interrupción externa:
- configuras un Timer para que salte cada X tiempo fijo, por ejemplo, cada 10ms.
- configuras el otro timer para que cuente pulsos externos
- cada 10ms lees los pulsos que han entrado y multiplicas por 100, esos serán los pulsos de un segundo.