Autor Tema: Valores del timer  (Leído 3969 veces)

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

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Valores del timer
« en: 03 de Noviembre de 2004, 06:51:00 »
Ayer estuve haciendo pruebas con el comando SetTimer probando distintas combinaciones e intentando medir el tiempo.
La verdad es que después de haber leído bastante y de hacer varias pruebas no me queda del todo claro cuál es la fórmula correcta para deducir el número de veces que se ejecuta la interrupción por segundo.
¿Alguien puede dar una explicación más o menos clara?
Adicionalmente otra duda, si tengo un 18F452 a 10MHz con el fuse H4, ¿qué frecuencia de reloj tengo que usar en la fórmula 10 o 40 MHz?
Graciaaaas

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: Valores del timer
« Respuesta #1 en: 03 de Noviembre de 2004, 07:33:00 »
Pón el programita con valores y lo miramos.

Respecto a lo segundo, no he usado nunca el H4, supongo que incluirá a las dos frecuencias.

Un saludo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #2 en: 03 de Noviembre de 2004, 10:02:00 »
Luego cuando llegue a casa posteo el programita (si es que me han arreglado el ADSL que se me fue ayer) aunque, no obstante, más que conseguir que mi ejemplo funcione, me gustaría entender la generalidad de dicho cálculo.

Gracias por tu interés Pocher.

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
RE: Valores del timer
« Respuesta #3 en: 03 de Noviembre de 2004, 14:23:00 »
Hola

La formula para saber el valor que debes de poner en SET TIMER, en funcion del tiempo, es:

256 - (tiempo /  (4/FOSC) )    

El tiempo (el delay del timer) , es en segundos, por lo que 35 micro segundos serian 0,000035 segundos, no lo olvidemos. FOSC en hercios jeje

Para 35 micro segundos de delay a 20mhz:

256 - (0.000035 / (4/20000000) ) = 81

El timer debe ser de 8 bits para aplicar la formula, creo.

salu2

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #4 en: 03 de Noviembre de 2004, 15:04:00 »
Gracias por la info Manex.
Os pongo a continuación el código sobre el que se me ha planteado la dudaloco.

Concretamente, mi intención es cronometrar el tiempo que tarda el bucle for en el que se está cogiendo muestras del ADC.

Para ello, he establecido los contadores como véis en el código y luego hay un intento de fórmula que debe dar los milisegundos, pero está hecho con el método de prueba y error, así que seguro que no es correctoSonrisa Gigante.

Por cierto, me interesaría que el cronometraje fuese bastante preciso.

Gracias amigos

Codigo:
#include <18F452.h>


#use delay(clock=40000000)
#fuses H4 , NOLVP , NOWDT

#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N)
#define TRAMA 400


#ifndef __PCH__
 #error This example is only for PIC18
#endif

#byte ADCON0=0XFC2
#byte ADCON1=0XFC1
#byte  ADRESH=0xfc4
#byte  ADRESL=0xfc3
int16 Ciclos;

#int_rtcc
void clock_isr() {
    Ciclos++;
}

void CogeMuestra1(){
ADCON0=0b10000001;
#asm
  bsf ADCON0,2       ;start conversion
wait1:
  btfsc   ADCON0,2
  goto   wait1         ;wait conversion completed
#endasm
   //   return ADRESh ;
}

void main()
   {

   int8 valores1[TRAMA];
   int16 numvalor,  HaTardado;

   ADCON0=0b10000001;
   ADCON1=0b01000000;

   set_timer0(0);
   setup_counters( RTCC_INTERNAL, RTCC_DIV_2 | RTCC_8_BIT);
   
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);

   while (1) {
         Ciclos=0;
         for (numvalor=0;numvalor<TRAMA;numvalor++) {
            CogeMuestra1();
            valores1[numvalor]=ADRESh;
         };
         HaTardado = (long)((float)Ciclos / 22 * 1000) ;  
         printf ("%5lu",HaTardado);
   }

Desconectado wqtrp

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 170
RE: Valores del timer
« Respuesta #5 en: 03 de Noviembre de 2004, 18:04:00 »
hola,
a Ciclos deberias multiplicarla por 256 ya q pusiste un timer de 8 bits, y a eso deberias sumarle el valor del timer0 (q puede ser despreciable.. o no, dependera del primer valor))
este valor total te dara cuanto ciclos tardo la muestra...
como estas a 4MHz seran microSeg.
pero al agregarle el H4 seran cuartos de microsegundos, o sea en ese caso debes dividir por 4 para tener el dato en microseg.

a ver como queda

   ((ciclos*256)+timer0)/4 ---> esto seran microseg.

en realidad acabo de vre q pusiste el timer con divisor de 2 con lo cual interrumpira cada 512 en lugar de 256, asi q se multiplica por 512 y el valor es el doble...

otra opcion es poner una variable dentro del loop de espera de conversion y ver cuanto da, y el el listado de assembler, ver cuantas instrucciones tiene el ciclo y multiplicar..

pero si queres realmente tener presicion deberias poner el timer0 en 16 bits sin divisor (x1) y q al interrumpir cuente en ciclos ( no se si sera necesario, pero por las dudas)...
por otro lado el timer0 debe ser puesto a cero mas cerca del inicio de la rutina de control...
y siempre tener en cuenta el H4, que yo lo deshabilitaria al menos al principio para tener una incertidumbre menos....

Suerte.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: Valores del timer
« Respuesta #6 en: 04 de Noviembre de 2004, 02:28:00 »
Si lo quieres hacer exactamente abre el fichero .lst, verás en él que el bucle for se descompone en instrucciones en ensamblador. Cuenta con cuidado y sin equivocarte todos los ciclos máquina del for y multiplicalos por lo que tarda 1CM que en este caso será 4/fosc=4/40MHz y tendras el resultado en us,

Por supuesto haciéndolo así te sobra la interrupción del TMR0.

Un saludo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #7 en: 04 de Noviembre de 2004, 04:35:00 »
Ciertamente me parece mucho más preciso saber el tiempo que tardan las instrucciones que están en el bucle y he comenzado a "desgranar" el LST y a contar los ciclos de reloj que se van gastando en cada paso, pero vuelvo con una nueva duda.
Pego el LST a continuación para que quede más claro donde me he atrancado:


Codigo:
*
0000:  GOTO   0004
....................  #include <18F452.h>
....................  
.................... #device PIC18F452  
.................... #list  
....................  
....................  
....................  
.................... #use delay(clock=40000000)  
.................... #fuses H4 , NOLVP , NOWDT  
....................  
.................... #ifndef __PCH__  
....................  #error This example is only for PIC18  
.................... #endif  
....................  
.................... #byte ADCON0=0XFC2  
.................... #byte ADCON1=0XFC1  
.................... #byte  ADRESH=0xfc4  
.................... #byte  ADRESL=0xfc3  
....................  
.................... void main()  
....................    {  
0004:  CLRF   FF8
0006:  BCF    FD0.7
0008:  CLRF   FEA
000A:  CLRF   FE9
000C:  BSF    FC1.0
000E:  BSF    FC1.1
0010:  BSF    FC1.2
0012:  BCF    FC1.3
....................  
....................    int8 valores1[400];  
....................  
....................    int16 numvalor;  
....................  
....................    ADCON0=0b10000001;  
0014:  MOVLW  81
0016:  MOVWF  FC2
....................    ADCON1=0b01000000;  
0018:  MOVLW  40
001A:  MOVWF  FC1
....................  
....................          for (numvalor=0;numvalor<400;numvalor++) {  
001C:  MOVLB  1         2 ciclos
001E:  CLRF   x97      2 ciclos
0020:  CLRF   x96      2 ciclos
0022:  MOVF   x97,W      2 ciclos
0024:  SUBLW  01      2 ciclos
0026:  BNC   0052      2 ciclos
0028:  BNZ   0030      2 ciclos
002A:  MOVF   x96,W      2 ciclos
002C:  SUBLW  8F      2 ciclos
002E:  BNC   0052      2 ciclos

....................             ADCON0=0b10000001;  

0030:  MOVLW  81      2 ciclos
0032:  MOVWF  FC2      2 ciclos

....................                #asm  
....................                  bsf ADCON0,2       

0034:  BSF    FC2.2      2 ciclos

....................                wait1:  
....................                  btfsc   ADCON0,2  

0036:  BTFSC  FC2.2      2 ciclos * n veces (tiempo ADC)

....................                  goto   wait1         

0038:  BRA    0036      2 ciclos * n veces (tiempo ADC)

....................                #endasm  
....................             valores1[numvalor]=ADRESh;  

003A:  MOVLW  06      2 ciclos
003C:  ADDWF  x96,W      2 ciclos
003E:  MOVWF  FE9      2 ciclos
0040:  MOVLW  00      2 ciclos
0042:  ADDWFC x97,W      2 ciclos
0044:  MOVWF  FEA      2 ciclos
0046:  MOVFF  FC4,FEF      2 ciclos
....................          };  
004A:  INCF   x96,F
004C:  BTFSC  FD8.2
004E:  INCF   x97,F
0050:  BRA    0022
....................  
....................    }  
....................  
0052:  SLEEP

Configuration Fuses:
   Word  1: 2600   H4 NOOSCSEN
   Word  2: 0E0F   BROWNOUT WDT128 NOWDT BORV20 NOPUT
   Word  3: 0100   CCP2C1
   Word  4: 0081   STVREN NODEBUG NOLVP
   Word  5: C00F   NOPROTECT NOCPD NOCPB
   Word  6: E00F   NOWRT NOWRTD NOWRTB NOWRTC
   Word  7: 400F   NOEBTR NOEBTRB


Pues bien, veréis que he puesto la frase "2 ciclos" en aquellas instrucciones que están dentro del for (creo que eso está bien pero no estoy seguro) pero hay dos instrucciones que son un sub-bucle en ASM, que espera a que finalice la conversión del ADC.
En estas dos instrucciones he puesto "2 ciclos * n veces".

He estado mirando la data del 18F452 para ver cual es ese tiempo y ya es cuando me he vuelto loco completamenteloco, porque según dice ahí, ese tiempo depende de CHold, de RS, del Error de conversión, de VDD, de la temperatura y de VHold, variables que no controlo.

¿Existe algún atajo para calcular esto o va a resultar más complicado que el famoso Fourier? Gracias

Desconectado wqtrp

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 170
RE: Valores del timer
« Respuesta #8 en: 04 de Noviembre de 2004, 05:33:00 »
exactamente alli es donde te decia de poner un contador, pq ese dato es real y depende de tantos factoers q sera imposible clacularlo empiricamente.

pero insisto q lo mas adecuado en relacion tiempo/esfuerzo, seria poner el timer en 16 bits, deshabilitar inicialmente el PLL y ve cuanto da.
luego habilitar el PLL y hacerlo de nuevo.


Suerte....

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #9 en: 04 de Noviembre de 2004, 05:51:00 »
Pues vuelta a empezar... Llorando

Gracias wqtrp

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #10 en: 04 de Noviembre de 2004, 16:43:00 »
Finalmente he seguido dándole vueltas a la opción de cronometrar el bucle y lo he conseguido, aunque no estoy nada contento porque el método ha sido casi el de prueba y error.
He cogido un generador de señal, la he sampleado con el bucle, he contado cuántas crestas de la onda han pasado por allí y he deducido qué retardo debería estar calculando la fórmula. Así hasta que he dado con ella.

Lo posteo a continuación, pero me gustaría que alguien le encontrase la lógica porque yo no lo consigo. Gracias.

Codigo:
#include <18F452.h>

#use delay(clock=40000000)
#fuses H4 , NOLVP , NOWDT

#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N)
#define TRAMA 500

#ifndef __PCH__
 #error This example is only for PIC18
#endif

#byte ADCON0=0XFC2
#byte ADCON1=0XFC1
#byte  ADRESH=0xfc4
#byte  ADRESL=0xfc3

void main()
   {

   int8 valores1[TRAMA];
   int8 valores2[TRAMA];

   int16 numvalor,  HaTardado;

   ADCON0=0b10000001;
   ADCON1=0b01000000;

   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   setup_timer_0( RTCC_INTERNAL);
   output_high (PIN_B3);      // es un led que se enciende al arrancar
   output_high (PIN_B0);
   delay_ms (100);         // lo mantengo encendido 3 décimas de segundo
   output_low (PIN_B3);         // y lo apago
   output_low (PIN_B0);
   delay_ms (100);
   while (1) {
         output_high (PIN_B3);

         set_timer0(0);
         for (numvalor=0;numvalor<TRAMA;numvalor++) {
            #asm
              bsf ADCON0,2       ;start conversion
            wait1:
              btfsc   ADCON0,2
              goto   wait1         ;wait conversion completed
            #endasm
            valores1[numvalor]=ADRESh;
         };
         HaTardado = (get_timer0()/40+7)/5*4; // número de microsegundos de la captura
         output_low (PIN_B3);

         printf ("%C%C%C%C%5lu",0x00,0xFF,0x00,0xFF,HaTardado);
         output_high (PIN_B0);
         for (numvalor=0;numvalor<TRAMA;numvalor++) {
            printf ("%C",valores1[numvalor]);
         };

         output_low (PIN_B0);
   };
   }

Desconectado wqtrp

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 170
RE: Valores del timer
« Respuesta #11 en: 04 de Noviembre de 2004, 17:26:00 »
si, pero finalmente no tenemos ni idea de cuanto ha tardado una medicion ni 500, ni el valor del timer0 ni nada de eso, dale, tira algunos valores al menos, ya q yo l menos no tengo ni idea cuanto tarda, solo lo uso y listo....

ahora de tu formula, si supieramos algunos valores.... algo se podria decir...
yo despreciaria el 7 dado q supongo el timer0 es grande , con lo cual me da timer0/50 q solo se parece a la cantiad de muestras q calculas pero dividido por 10, no se te escapo un cero?.....

esperamos a ver como es....


Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #12 en: 04 de Noviembre de 2004, 23:51:00 »
Le metí una onda de 1 Khz, y he contado el número de ciclos de onda que ha sampleado el bucle y han sido justo 10, con lo que ya supe que, sea como sea, el bucle había tardado 10ms, por lo que adapté el valor que devuelve get_timer para que el resultado fuera 10.

Desconectado cucaracha

  • PIC24H
  • ******
  • Mensajes: 1409
    • CUCAWEB
RE: Valores del timer
« Respuesta #13 en: 05 de Noviembre de 2004, 05:53:00 »
yo hay una cosa que no entiendo en tu programa... Para que activas la interrupción del RTCC si luego no la usas??
Además, 10ms con el el timer0 sin preescala(que sería lo indicado)??? Me parece que se desbordaría varias veces, y como tienes activa la interrpción, ciclos que pierdes, ya que entrar en la interrupción entra, aunque luego no tenga nada que hacer.
Eso... 10ms.... quizás me equivoque.. pero comprueba eso.
No se.. nunca usé la interrupción del AD, pero quizás con esa y con la del timer... sería activar ambas. Poner a convertir y que el tiemer se vaya desbordando. Un registro para contar esos desbordamientos. Luego, cuando salte la del AD, leería entonces el timer, y sería pues (256*veces que desbordóGiño+lectura última del timer.
Esos serían más o menos los ciclos que tardó. Se podría ajustar algo viendo los ciclos que tarda en entrar y limpiar el timer cuando salta su int y lo mismo cuando salta el AD... y quizás alguna cosilla más. Pero es para una idea...
Luego con los ciclos y teniendo el tiempo por ciclo, es cuestión de multiplicar. En tu caso, sería 100ns por ciclo (para cristal de40mhz).
En fin, espero no liarte. Es una opinión así de pronto...

Saludos!!
Saludos desde Huelva (ESPAÑA)

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Valores del timer
« Respuesta #14 en: 05 de Noviembre de 2004, 07:41:00 »
Tardaré un buen rato en digerir tu mensaje Cuca, aunque sí te comento que la interrupción del RTCC la tenía activa en la versión anterior del programa y se me olvidó quitarla, pero como tú dices no sirve más que para estorbar.

Con respecto a lo que comentas de la interrupción del AD, no sé cómo se usa, pero investigaré.

Gracias monstruo