Autor Tema: Cosas raras midiendo un pulso con pic18f4620  (Leído 1886 veces)

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

Desconectado pieromichelle

  • PIC10
  • *
  • Mensajes: 12
Cosas raras midiendo un pulso con pic18f4620
« en: 10 de Septiembre de 2009, 07:16:22 »
Hola gente del foro. Tengo una duda sobre el uso del modulo CCP2. Supuestamente al usar este modulo teniendo un tren de pulsos entrando por RB3, lo que ocurrira en cada flanco de subida es que se entrara a una rutina de interrupcion y se cargara automaticamente el registro de 16 bits de este comparador con el valor del timer 1, luego configuro el modulo para que vuelva a entrar a la rutina de interrupcion en el flanco de bajada y que me capture un nuevo valor. Hago esto para medir el ancho de los pulsos. La instruccion que se usa en estos casos es CCP_2, la cual luego yo cargo en una variable creada por mi. Tengo que comentar que mi programa es casi una copia fiel del ejemplo utilizado por RedPic o RedRaven. Ahora, mi duda era saber cual es en realidad la ventaja de utilizar esta funcion cuando usando el get_timer1() hago lo mismo. Es decir probablemente el pic al usar CCP_2 automaticamente cargue el valor del timer1 en un registro (si no me equivoco CCPR2), pero luego yo tengo que cargar lo que hay en CCPR2 en mi variable; que es lo mismo que cargar en mi variable directamente el valor que esta en el timer1 en ese momento. Ahora, supuestamente estos 2 metodos deberian entregarme los mismos resultados, pero no es asi. No se si yo me estoy olvidando de hacer algo o que es lo que pasa. A continuacion copiare mi programa para que lo puedan ver:


/***********************************************************************************/
/* Dispositivo: PIC18f4620                                                         */
/* Autor: Piero Michelle Gavidia Panesi                                            */
/***********************************************************************************/
#include "18F4620.h"
#include <stdlib.h>
#fuses INTRC,NOWDT,NOMCLR,PUT,BROWNOUT,PROTECT,CCP2B3
#use delay (clock=4000000,restart_wdt)
#use rs232(baud=9600,bits=8,parity=N,Stop=1,xmit=PIN_C6,rcv=PIN_C7,restart_wdt)
////////////////////////////////////////////////////////
// VARIABLES                                          //
////////////////////////////////////////////////////////
int1 Cambio_Flanco=0;
int1 Hay_Datos=0;
int16 T1a,T2a,T1b,T2b;
////////////////////////////////////////////////////////
// FUNCIONES                                          //
////////////////////////////////////////////////////////
void config_puertos(void)

   set_tris_D(0x00);   
   set_tris_C(0xFB);    // RC2 como salida 
   port_b_pullups(TRUE);
   set_tris_B(0x1F);    // Puerto B - Entradas

//////////////////////////////////////////////////////////////////
//                             MAIN                             //
//////////////////////////////////////////////////////////////////
void main()
{   
 config_puertos(); 

 disable_interrupts(GLOBAL);
 //setup_timer_1(T1_INTERNAL);
 setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);          // inicializo el Flag para cambiar de flanco
 setup_timer_3(T3_DISABLED);
 setup_ccp2(CCP_CAPTURE_FE);     // Configuro captura de 1er flanco de subida
 enable_interrupts(int_ccp2);
 enable_interrupts(GLOBAL);
 Cambio_Flanco = 0;     
 set_timer1(0);              // Reinicio TMR1
 
while(1)
 { 
    if(Hay_Datos==1)           // Detecto que ya hay datos de flancos ...
    {   
       printf("T1a = %Lu uS  T2a = %Lu uS  T1b = %Lu uS  T2b = %Lu uS  \r\n\n",T1a,T2a,T1b,T2b);
       Hay_Datos=0;
     }
 } 
}
/*****************************************************************************
********************** RUTINA DE INTERRUPCION *******************************
*****************************************************************************/
#int_ccp2
void handle_ccp2_int()
{
    if(Cambio_Flanco==0)       // He recibido Flanco de Subida
    {     
      T1a=CCP_2;
      T2a=get_timer1();
     
      setup_ccp2(CCP_CAPTURE_RE); // Configuro para capturar siguiente flanco de Bajada
      Cambio_Flanco=1;         // Indico que el siguiente flanco será de Bajada
    }
    else                          // He recibido Flanco de Bajada
    {                     
      T1b=CCP_2;
      T2b=get_timer1();            // Guardo en T el valor de TMR1 al Flanco de Bajada
   
      setup_ccp2(CCP_CAPTURE_FE); // Configuro para capturar siguiente flanco de subida
      Cambio_Flanco=0;         // Indico que el siguiente flanco será de Subida
      Hay_Datos=1;     
      set_timer1(0);              // Reinicio TMR1
    }               
}

Y los resultados que obtengo por el hiperterminal (en realidad el docklight que es similar) es lo siguiente:

T1a = 5 uS  T2a = 87 uS              T1b = 111 uS  T2b = 186 uS  <CR><LF>

Como ven T1a y T2a en vez de tener los mismos valores (o al menos con un par de uSegs de diferencia), tienen valores muy distintos, con 82uS  de diferencia habiendose ejecutado la instruccion una a continuacion de la otra. Lo mismo pasa con las variables T1b y T2b que cargo en el flanco de bajada. Ojo que me he adentrado en el codigo en ensamblador y no hay muchas instrucciones adicionales; digamos que en el caso de T1a directamente esta variable es cargada con lo que hay en CCPR2 y la variable T2a es cargada con lo que hay en TMR1.
Que esta ocurriendo?? Alguien me podria ayudar? Lo agradeceria mucho.
Saludos
Piero

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cosas raras midiendo un pulso con pic18f4620
« Respuesta #1 en: 10 de Septiembre de 2009, 09:57:41 »
No son exactamente los mismo, como bien tu dice el módulo CCP lo hace automáticamente guardando el valor en los registros correspondientes. En cambio si tu quieres hacer lo mismo pero leyendo directamente el timer, tooodas las instrucciones que se ejecutan para salvaguardar los registros y determinar que interrupción se ha generado te crea un error.



Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado pieromichelle

  • PIC10
  • *
  • Mensajes: 12
Re: Cosas raras midiendo un pulso con pic18f4620
« Respuesta #2 en: 10 de Septiembre de 2009, 11:45:11 »
Hola Suky. Gracias por responder. No se a que tipo de error te refieres. El programa que he publicado no genera ningun error de compilacion, mas si de los resultados que se esperan. Usando la interrupcion del modulo CCP2, el programa igual salta a esa rutina solo que antes de hacerlo ya cargo el valor del timer1 en un registro. Yo lo que hago en un caso es leer de ese registro y copiarlo a una variable y en el otro caso leo directamente del timer1. Entre una accion y la otra no hay tantas instrucciones que puean generar un ratardo de 81 uS (aprox). Recordar que uso el cristal interno de 4Mhz con lo que tengo 1 uS por ciclo de instruccion. Aun no me explico que pasa y realmente cual es la ventaja de usar este modulo en modo captura ya que si uno captura un valor es para salvarlo en otra variable y no para dejar que esa informacion se chanque sucesivamente en el registro CCPR2. Ojala alguien pruebe el programa para saber si obtiene los mismos resultados. Resumo, si hay aguna diferencia entre uno y otro metodo, no deberia ser mas de 5 uS.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Cosas raras midiendo un pulso con pic18f4620
« Respuesta #3 en: 10 de Septiembre de 2009, 12:07:40 »
El error que comentas tu!!! Que las mediciones son distintas  :undecided: Y la causa ya esta explicada en el mensaje anterior.
No contesto mensajes privados, las consultas en el foro

Desconectado pieromichelle

  • PIC10
  • *
  • Mensajes: 12
Re: Cosas raras midiendo un pulso con pic18f4620
« Respuesta #4 en: 12 de Septiembre de 2009, 20:14:35 »
Hola a todos. Aun no me queda claro que sucede. A pesar de la ultima respuesta. Alguien probo el programa? Alguien me puede dar una respuesta mas completa?
Lo agradeceria.
Saludos
Piero

Desconectado pieromichelle

  • PIC10
  • *
  • Mensajes: 12
Re: Cosas raras midiendo un pulso con pic18f4620
« Respuesta #5 en: 25 de Septiembre de 2009, 09:34:27 »
Hola gente. En vista que nadie despejo mi duda con la presicion que yo queria, solo queria comentar que hace unas semanas descubri en que me estaba equivocando. Esto es solo por si alguien mas comete el mismo error. Probablemente las 2 formas de leer el valor del timer1 sean igual de exactas (creo que con algunos useg de diferencia), me refiero a CCP_2 y get_timer1(). Lo que pasa es que al ser la frecuencia de mis pulsos muy alta (periodo de alrededor 150us) la rutina de interrupcion se ejecutara muchas veces. Y al usar el printf cada vez que envio un caracter por el puerto serie ese es un tiempo que va transcurriendo y que es mayor de los 150us. Veamos:

Esto es lo que obtengo a la salida de mi programa

T1a = 5 uS  T2a = 87 uS              T1b = 111 uS  T2b = 186 uS  <CR><LF>

El primer valor de T1a es el bueno, pero el valor de T2a llega despues de que he enviado como 11 caracteres por el puerto serie y para esto la rutina de interrupcion ya se ejecuto varias veces y capturo distintos valores para T2a. los 11 caracteres son " uS  T2a = " (probablemente mas).

Espero que me haya hecho entender y que esta observacion le sirva a alguien.

Saludos.


 

anything