Autor Tema: Retardo en rutina de interrupciones (Timer1)  (Leído 2848 veces)

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

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Retardo en rutina de interrupciones (Timer1)
« en: 14 de Octubre de 2014, 13:55:40 »
Buenas!

Estoy intentando programar en CSS (aunque mi problema es de interrupciones, así que espero no haberme equivocado de subforo) un encoder/decoder para código Manchester. Ya lo tengo funcionando, pero quiero lograr mayor precisión tanto en recepción como en transmisión, por lo que me he metido con el tema de las interrupciones.

Las pruebas las estoy haciendo sobre un PIC12F683, y estoy utilizando el Timer 1 (sin prescaler, para simplificar -> 1 ciclo = 1us). De momento he configurado la rutina de interrupciones, y trato de que se ejecute cada 100 us. Para ello, cargo el Timer1 con el valor (65536-100), de modo que se desbordará cada 100 ciclos = 100us. Debería obtener un pulso cada 100us, pero lo obtengo cada ~137us. Me parece un error bastante grande tratándose de interrupciones. Si realizo una corrección y cargo el timer con  (65536-100+37), todo perfecto, 100us clavados, a pesar de ser una chapuza. No lo he probado con otros PICs.

A lo que voy... ¿Es normal este comportamiento, o alguien sabe a qué podría deberse y cómo corregirlo?

Muchas gracias!!


Mi código:

Código: [Seleccionar]
#include <12F683.h>
#FUSES NOMCLR    //Master Clear pin used for I/O
#FUSES INTRC
#use delay(clock=4M)
#use fast_io(A)

#bit PIN0 = 0x05.0

#int_TIMER1
void  TIMER1_isr(void) //Función de interrupción por desbordamiento TMR1  
{
set_timer1(65536-100+37); // Carga del TMR1 -> Con este valor, las interrupciones se disparan cada 100us
PIN0 = 1;
PIN0 = 0;
}

void main()
{
set_tris_a(0x00);

setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // TIMER1: Clock Interno, Prescaler 1 (Para 4MHZ -> Incrementos cada 1us)
enable_interrupts(INT_TIMER1); // Habilito interrupción particular del TIMER1
enable_interrupts(GLOBAL); // Habilito interrupciones globales
set_timer1(65536-100); // Carga del TMR1 -> Con este valor, la primera interrupción se dispara 137us después
  
while(1);
}
« Última modificación: 14 de Octubre de 2014, 13:58:07 por sysseon »

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #1 en: 14 de Octubre de 2014, 17:15:47 »
A mí me parece normal, ya que detrás de un código de alto nivel (en este caso C), existe código oculto que se ejecuta antes y durante la interrupción (por ejemplo se salva registros antes de saltar al vector de interrupción).
La interrupción sucede cuando el valor del timer pasa de 0xFF a 0x00 (si el timer es de 8 bits), o de 0xFFFF a 0x0000 (si es de 16 bits). No conozco al PIC12F.

Una vez que sucede la interrupción, hasta que sea atendida por tu código, habrá alcanzado un valor mayor que 0x00 (ó 0x0000).

Ese valor es la latencia de tu interrupción y debe ser considerada para calibrar nuevamente tu timer1.

En este caso puedes corregir el error (debido a la latencia) obteniendo el valor del temporizador antes de ejecutar la función set_timer1 o de manera empírica como tú ya lo has realizado.

Si deseas saber porque se demora tanto, deberías ejecutar tu proyecto en lenguaje ensamblador (desensamblando tu código en C) y ver que realmente hace antes de atender tu interrupción. No se si se puede realizar eso en CSS.
« Última modificación: 14 de Octubre de 2014, 18:23:16 por DominusDRR »
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #2 en: 14 de Octubre de 2014, 19:51:07 »
  Concuerdo con DominusDRR. Ese comportamiento es normal.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #3 en: 14 de Octubre de 2014, 20:29:21 »
....Si realizo una corrección y cargo el timer con  (65536-100+37), todo perfecto, 100us clavados, a pesar de ser una chapuza. No lo he probado con otros PICs.
...


si quieres precisión en C, eso es lo que debes hacer, aunque yo comprobaría mirando el tiempo y el cambio en los registros que a fin de cuentas es lo que importa
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado KALLITOS

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1256
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #4 en: 14 de Octubre de 2014, 21:17:37 »
A mi me paso algo parecido cuando hice un pulsos con pasos de 100 us. Segun los calculos matematicos no coinciden ya que el valor de 100 us da 57 us, pero medido en fisico me dio 100 us, entonces tuve que hacer una tabla como la que sigue, y logré los tiempos aceptables, hay que tener en cuenta lo que mencionan de que estamos usando CCS que no es ASM, entonces no es exacto.

Realizado con CCS V 5.007   pic16f648   4Mhz Oscilador Interno

te pongo mi tabla:

Código: C
  1. #define  valor_100us       65478
  2. #define  valor_200us       65380
  3. #define  valor_300us       65280
  4. #define  valor_400us       65180
  5. #define  valor_500us       65080
  6. #define  valor_600us       64980
  7. #define  valor_700us       64880
  8. #define  valor_800us       64780
  9. #define  valor_900us       64680
  10. #define  valor_1000us      64580
  11. #define  valor_1100us      64480
  12. #define  valor_1200us      64380
  13. #define  valor_1300us      64280
  14. #define  valor_1400us      64180
  15. #define  valor_1500us      64080
  16. #define  valor_1600us      63980
  17. #define  valor_1700us      63880
  18. #define  valor_1800us      63780
  19. #define  valor_1900us      63680
  20. #define  valor_2000us      63580
  21. #define  valor_2100us      63480
  22. #define  valor_2200us      63380
  23. #define  valor_2300us      63280
  24. #define  valor_2400us      63180
  25. #define  valor_2500us      63080
  26. #define  valor_2600us      62980
  27. #define  valor_2700us      62880
  28. #define  valor_2800us      62780
  29. #define  valor_2900us      62680
  30. #define  valor_3000us      62580

saludos.
A un microcontrolador hay que sacarle hasta el ultimo byte....(YO)

Cómo puede ser que un pic24EP512 me quede corto de memoria, señores de MICROCHIP saquen pics con más memoria flash

Más de 45 mil lineas de codigo y aun no termino el equipo, asu mare!!

S34ML08G1TFI200 no necesito mas memoria externa.

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #5 en: 14 de Octubre de 2014, 22:38:46 »
Perfecto, muchas gracias a todos por las respuestas. Me parece bastante cutre la solución, porque resta portabilidad y legibilidad al código, pero ya veo que no hay otra manera de hacerlo (me parece un fallo importante de un compilador, no sé... siendo así, puede ser mejor el polling a las interrupciones). He intentado corregir el error desde el propio manejador de interrupciones, pero solo con la lectura de los registros y demás... al final es mejor usar un valor fijo calculado previamente.

Bueno, estoy contento con la precisión que he conseguido. Si más adelante quiero pulir esto un poco más, me miraré el tema de ASM como habéis comentado.

Gracias de nuevo!

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #6 en: 14 de Octubre de 2014, 23:09:55 »
yo pienso que tiene que ver con aquello de las 5 lineas de asm por cada linea del C (según un libro de micros que leí hace años), pero en ensamblador podría presentarse un caso similar, imagina que entre esos 100us el contador de programas pasa por 30 condiciones de salto, entonces dependiendo del proceso (condiciones de variables o pines de entradas) habrá veces que en esas 30 condiciones, salten 15 y las otras no, o salten 3 y el resto no, etc. entonces también tendrías que tomar en cuenta los saltos del contador, por lo que se ganaría en el mejor de los casos 1us. También está el hecho de la variación de reloj, como temperatura, perdida de precisión con el tiempo, etc.
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado sysseon

  • PIC10
  • *
  • Mensajes: 20
Re: Retardo en rutina de interrupciones (Timer1)
« Respuesta #7 en: 15 de Octubre de 2014, 16:10:37 »
Bueno, no sé qué comportamiento tendría este tema de interrupciones en ASM, nunca lo he probado. Pero bueno, yo uso CCS y cuando compilas el código puedes ver la conversión de cada línea en ensamblador... y no sé, parece bastante eficiente (no me refiero a líneas que obviamente se descompondrán en un montón más, como operaciones aritméticas y demás). Por eso me chocó lo de los ~35us de retardo para ejecutar una rutina de interrupciones, pero bueno, entiendo que pueda ser normal (puede que idealice demasiado el comportamiento de estas cosas a veces).


 

anything