Autor Tema: Entendiendo el TIMER0 en CCS  (Leído 34443 veces)

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

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1697
Entendiendo el TIMER0 en CCS
« en: 09 de Julio de 2009, 17:30:50 »
Bueno, resulta que me dispuse a entender el  manejo del TIMER0 en CCS, entonces como aun soy bastante novato pues todo lo hago a traves del PICwizard, el picwizard me arroja las opciones de poder configurar el prescaler:

En donde entiendo que el timer se incrementará en "1 unidad" cada 2,4,8,16,32,64,128,256 y asi mismo el timer me muestra un overflow que seria el tiempo en que demoraria el TIMER0 en desbordarse.
Dicho lo anterior se tiene que:

prescaler     overflow
2                    512     uS
4                    1        mS aprox
8                    2        mS aprox
16                  4        mS aprox
32                  8.1     mS aprox
64                  16.3   mS aprox
128                32.7   mS aprox
256                65.5   mS aprox

ahora entonces para hacer la prueba de que todo lo que asumo es cierto hice el siguiente codigo, en donde configuré un prescaler de 8 con lo cual voy a obtener una interrupcion cada 2 mS aproximadamente, a partir de los 2 mS obtengo 1 Seg y muestro el incremento de una variable en el lcd
#INCLUDE "FLEX_LCD.C"

Código: CSS
  1. CHAR I=0;
  2. INT16 A;
  3.  
  4. #int_RTCC
  5. void  RTCC_isr(void)
  6. {
  7. A++;
  8. IF(A==500)                   // ha pasado 1 Seg?
  9.    {
  10.    A=0;                         //Si,repongo contador
  11.    I++;                         //incremento de variable a mostrar en lcd
  12.    }
  13. }
  14.  
  15. void main()
  16. {
  17.  
  18.    setup_adc_ports(NO_ANALOGS);
  19.    setup_adc(ADC_OFF);
  20.    setup_psp(PSP_DISABLED);
  21.    setup_spi(SPI_SS_DISABLED);
  22.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
  23.    setup_timer_1(T1_DISABLED);
  24.    setup_timer_2(T2_DISABLED,0,1);
  25.    setup_comparator(NC_NC_NC_NC);
  26.    setup_vref(FALSE);
  27.    
  28.  
  29.    LCD_INIT();
  30.    enable_interrupts(INT_RTCC);
  31.    enable_interrupts(GLOBAL);
  32.    FOR(;;)
  33.     {
  34.     LCD_GOTOXY(1,1);
  35.     PRINTF(LCD_PUTC,"NUM %u",I);
  36.    
  37.     }
  38.  
  39.   }


simulando veo q funciona pero los tiempos no son muy exactos y al cabo de un tiempo el desfase puede ser considerable


ahora tambien hice otro programa cambiando el prescaler a 256, con lo cual obtendré un tiempo de overflow= 65.5 mS, entonces le cargo al timer el valor 195 y con esto obtengo un overflow de 49.92 mS aprox 50mS entonces lo unico que deberia hacer es cambiarle  el valor de la variable de control para saber si ya pasó un segundo, entonces seria asi:
Código: CSS
  1. #INCLUDE "FLEX_LCD.C"
  2.  
  3.  
  4. CHAR I=0;
  5. char A;
  6.  
  7. #int_RTCC
  8. void  RTCC_isr(void)
  9. {
  10. A++;
  11. IF(A==20)
  12.    {
  13.    A=0;
  14.    I++;
  15.    }
  16.      
  17. }
  18.  
  19.  
  20.  
  21. void main()
  22. {
  23.  
  24.    setup_adc_ports(NO_ANALOGS);
  25.    setup_adc(ADC_OFF);
  26.    setup_psp(PSP_DISABLED);
  27.    setup_spi(SPI_SS_DISABLED);
  28.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
  29.    setup_timer_1(T1_DISABLED);
  30.    setup_timer_2(T2_DISABLED,0,1);
  31.    setup_comparator(NC_NC_NC_NC);
  32.    setup_vref(FALSE);
  33.    
  34.  
  35.    LCD_INIT();
  36.    enable_interrupts(INT_RTCC);
  37.    enable_interrupts(GLOBAL);
  38.    SET_TIMER0(195);
  39.    FOR(;;)
  40.    {
  41.    LCD_GOTOXY(1,1);
  42.    PRINTF(LCD_PUTC,"NUM %u",I);
  43.    
  44.    }
  45.  
  46.   }

supongo q en teoria deberia ser lo mismo..?¿?¿..pero de esta forma en mas inexacto el tiempo...por qué? como puedo hacer para ajustar mejor estos tiempos?
« Última modificación: 14 de Julio de 2009, 00:31:37 por jhozate »
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado juansi

  • PIC16
  • ***
  • Mensajes: 102
Re: Entendiendo el TIMER0
« Respuesta #1 en: 09 de Julio de 2009, 18:46:54 »
amigo jhozate, en principio yo tamien soy novato, pero voy a intentar ayudarte un poco.

Hay q tener en cuenta el cristal q usas(el oscilador interno es impreciso), tambien q nuestro pic aumenta el preescaler en 1 cada cuatro ciclos de relog, te aconsejo q mires los ejemplos de vszener "Ejemplitos en C para 16F648A", yo aprendi con ellos, ademas tiene un ejemplo con ajuste fino de un segundo.
Las mujeres quieren "SOLUCIONES", y los hombres lo mismo pero escrito al reves.

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1697
Re: Entendiendo el TIMER0
« Respuesta #2 en: 09 de Julio de 2009, 18:52:23 »
si de hecho yo tambien voy aprendiendo con ese hilo, pero la verdad no entiendo q se debe hacer y que hace vszener para hacer el ajuste del timer0, yo hace ratico vengo del assembler y ahí los tiempos son muy precisos, entonces no se si esas perdidas se podrian deber a q el programa es en C
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Entendiendo el TIMER0
« Respuesta #3 en: 09 de Julio de 2009, 19:11:12 »
En el último ejemplo, antes de salir de la interrupción debes volver a cargar con 195 para que se interrumpa otra vez cada 50ms :wink:
No contesto mensajes privados, las consultas en el foro

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1697
Re: Entendiendo el TIMER0
« Respuesta #4 en: 09 de Julio de 2009, 19:25:54 »
 :mrgreen: si, sin embargo  se pierde tiempo ...supongo q es un error acumulativo de ms q con el tiempo se puede volver importante
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado juansi

  • PIC16
  • ***
  • Mensajes: 102
Re: Entendiendo el TIMER0
« Respuesta #5 en: 09 de Julio de 2009, 19:45:48 »
recuerda q dentro de la interrupcion puedes ingeniarte otra variable para recuperar ese tiempo,tambien creo q hay cristales con los hercios justos para ajustar el timer.
Las mujeres quieren "SOLUCIONES", y los hombres lo mismo pero escrito al reves.

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: Entendiendo el TIMER0
« Respuesta #6 en: 13 de Julio de 2009, 11:26:15 »
TIMER0 + Escritura en TIMER0 <> Precisión

No se puede pretender tener precisión en la medición de tiempo utilizando este TIMER y escribiendo en él un valor de recarga. Las razones son varias:

Escribir en el TIMER implica cometer varios errores, algunos de ellos, con valores de tiempo que no se pueden medir, ni siquiera estimar.  Desde que el TIMER se desborda y pide interrupción, hasta que esta es atendida, puede transcurrir un tiempo variable, que depende de muchos factores, como por ejemplo:

*Tipo de instrucción que se está ejecutando (cuantos ciclos consume), Si está siendo atendida otra interrupción y durante ese proceso están deshabilitadas el resto, por lo tanto, no habrá posibilidad de atender la al TIMER0 hasta que termine la otra ISR.
*Existen además otras fuentes de error asociadas y más controlables, como el tiempo que toma escribir en el registro, los dos ciclos que consume el TIMER luego de ser escrito para comenzar a contar nuevamente, y que pueden ser tenidos en cuenta en una corrección del valor de recarga.

Las razones son una cuantas, y no creo que valga la pena enumerarlas todas, con las expuestas es más que suficiente.

Mi recomendaciones son

*Utilice TIMER0 sin recarga, siempre que se pueda
*Si desea utilizar TIMER0 con recarga por software de su registro de conteo, no lo haga pensando que obtendrá precisión en la medida de tiempo. Utilice este método para sincronizar procesos a intervalos regulares donde la precisión a lo largo del tiempo no sea una restricción de diseño (evite hacer relojes y cronómetros con este método)
*Si desea precisión, busque soluciones de temporización que incluyan hardware como elemento de conteo, que le garantice la precisión necesaria, por ejemplo TIMER2 o TIMER1+CCP en modo comparación.

Saludos
Reinier

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1697
Re: Entendiendo el TIMER0
« Respuesta #7 en: 14 de Julio de 2009, 00:30:59 »
ya.. :?...entonces no puedo esperear a q el Timer0 en CCS sea muy preciso, pero entonces, quisiera entender este ejemplo donde se hace un ajuste fino con el uso de una variable...no tengo claro el concepto o la estrategia a seguir
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado reiniertl

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1187
Re: Entendiendo el TIMER0 en CCS
« Respuesta #8 en: 15 de Julio de 2009, 08:52:21 »
No puedes esperar que este TIMER te de temporizaciones precisas de ninguna forma, excepto la que él por su propia naturaleza puede ofrecerte, es decir, contar desde 0 a 255, y provocar una petición de interrupción en su desbordamiento, uses el lenguaje que uses para programarlo.

Si modificas el registro de conteo para que el TIMER0 cuente un poco menos, digamos desde 100 a 255, porque si lo hace así te dará un período de interrupción más apropiado para lo que intentas hacer, se cometerán errores en la temporización, errores debido a la latencia del proceso de interrupción (tiempo que le toma al procesador comenzar a atender la interrupción luego de que esta se activa).

La latencia de la interrupción es el peor dolor de cabeza para este método porque es muy difícil predecir cuanto tiempo demorará el procesador en atender la interrupción, sobre todo si cuando el TIMER0 pide interrupción se está atendiendo a otra interrupción, ya que la forma más frecuente de atender interrupciones en PIC es enmascarar las interrupciones dentro de una ISR, lo que evita que las interrupciones se puedan anidar (así lo hace CCS por defecto). también depende de si la instrucción que se está ejecutando cuando llega el pedido de interrupción es de 1 o dos ciclos (como las de salto), de lo que le tome al proceso de discriminación de interrupciones decidir que es la del TIMER0 la que será atendida(recordemos que en PIC las interrupciones no son individualmente vectorizadas, existe un solo vector de interrupción y allí hay que decidir cual atender). Suma a ello que una vez en la ISR deberías leer el TIMER0 para saber cuantos períodos se han contado, hacer un cálculo de ajuste del valor de recarga, escribir el contador y esperar dos ciclos de máquina para que este recomience el conteo.

Muchas complicaciones para intentar conseguir una precisión que no se consigue. Ahora, esto no implica que este método se inútil, sino que hay que saber donde utilizarlo y donde NO.

Donde NO utilizarlo:
En aplicaciones que requieran temporizaciones precisas en un período largo de tiempo (entiéndase de 1 hora en adelante). Ya que los errores serán acumulativos y la temporización se verá afectada.

Ejemplos de estas aplicaciones:
Relojes calendarios
Cronómetros
Contadores largos que requieran precisiones de segundos (1 hora o más)

Donde sí tulizarla
Aplicaciones que requieran de tiempos relativamente precisos, pero donde la precisión a lo largo del tiempo no sea esencial, no importa la acumulación del error.

Ejemplos:
Sincronización de procesos (seteo y encuesta de banderas)
Temporización para procesos de encuesta como por ejemplo. Escribir una lámpara de 7 segmentos multiplexada, lectura de teclados, procesos de conversión con el AD (no siempre sirve, pero la mayoría de las veces sí)

Saludos
Reinier

Desconectado czeiss

  • PIC10
  • *
  • Mensajes: 5
Re: Entendiendo el TIMER0 en CCS
« Respuesta #9 en: 01 de Octubre de 2009, 13:14:13 »
Hola, a todos.
Cuando he tratado interrupciones para generar tiempo precisos lo he hecho con codigo en asm. Y dentro de la interrupcion solo ha dejado lo necesario para marcar que se produjo la interrupcion.
Para ajustar la base de tiempo, lo puedes hacer con el MPLAB que tiene un contador de tiempo de instruccion por instruccion watch .. algo no recuerdo bien.
En CCS es muy dificil que genere una base de tiempo precisa, ya que agrega codigo extra cual no esta contabilizado en el tiempo total de la interrupcion.
Recuerda que cuando se ingresa a la interrupcion se desabilita y por el ende el tiempo de las intrucciones que se ejecutan dentro no se ha contabilizado.

Desconectado dieguez07

  • PIC10
  • *
  • Mensajes: 7
Configuracion tmr0 18f452 en 16 bit
« Respuesta #10 en: 13 de Octubre de 2009, 08:10:22 »
Hola a todos. he intentado configurar el TMR0 y el TMR1 en 16 bit en un 18f452 y cuando lo simulo en el ISIS la parte alta del TMR no se incrementa y no se interrumpe en el tiempo calculado (si se interrumpe).
Alguno me podria dar una ayudita porque la verdad he intentado de varias maneras y sigue siempre igual. Sera problema del ISIS?
Bueno desde ya muchas gracias y espero una respuestita.
Saludos.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Entendiendo el TIMER0 en CCS
« Respuesta #11 en: 13 de Octubre de 2009, 09:28:10 »
Por lo que veo CCS el timer1 siempre lo va a usar en 16 bits:
Cita de: 18F452.h
////////////////////////////////////////////////////////////////// Timer 1
// Timer 1 Functions: SETUP_TIMER_1, GET_TIMER1, SET_TIMER1
// Constants used for SETUP_TIMER_1() are:
//      (or (via |) together constants from each group)
#define T1_DISABLED         0
#define T1_INTERNAL         0x85
#define T1_EXTERNAL         0x87
#define T1_EXTERNAL_SYNC    0x83

#define T1_CLK_OUT          8

#define T1_DIV_BY_1         0
#define T1_DIV_BY_2         0x10
#define T1_DIV_BY_4         0x20
#define T1_DIV_BY_8         0x30

Y al timer0 si no se le agrega la linea RTCC_8_BIT trabaja en 16 bits. Muéstranos como has realizado la temporización para poder detectar el error
No contesto mensajes privados, las consultas en el foro

Desconectado dieguez07

  • PIC10
  • *
  • Mensajes: 7
Re: Entendiendo el TIMER0 en CCS
« Respuesta #12 en: 13 de Octubre de 2009, 14:32:21 »
Gracias por su respuesta, lo he echo en basic de esta manera.

    Device 18F452                                                                                                                                                                                 
    XTAL 16

    ON_Interrupt GoTo Interrupcion
 
;---Congiguracion de la registros de config (para el 18F452)------------------------------------------------------------------------------------

    @CONFIG_REQ
    @__CONFIG config1h, HS_OSC_1 &  OSCS_OFF_1                                                         
    @__CONFIG config2l, BOR_OFF_2 & PWRT_ON_2                                                         
    @__CONFIG config2h, WDT_OFF_2 & WDTPS_1_2                                                         
    @__CONFIG config3h, CCP2MX_OFF_3                                                                   
    @__CONFIG config4l, DEBUG_OFF_4 & LVP_OFF_4 & STVR_OFF_4                                           
    @__CONFIG config5l, CP0_off_5 & CP1_OFF_5 & CP2_off_5 & CP3_OFF_5 ; si deseo protejer debo poner en ON esta linea                                                         
    @__CONFIG config5h, CPB_OFF_5 & CPD_off_5        ; protejo eeprom                                                 
    @__CONFIG config6l, WRT0_OFF_6 & WRT1_OFF_6                                                       
    @__CONFIG config6h, WRTB_OFF_6 & WRTC_OFF_6 & WRTD_OFF_6                                           
    @__CONFIG config7l, EBTR0_OFF_7 & EBTR1_OFF_7                                                     
    @__CONFIG config7h, EBTRB_OFF_7                                                                   
 
    OSCCON = 0                      ; Oscilador principal                                             
    RCON.7 = 0                      ; Prioridad de interrupciones deshabilitadas                       
    WDTCON.0=0                      ; El oscilador del wdt esta deshabilitado                         
    TMR0L = 0                       ; Borro el registro timer 0                                       
    TMR0H = 0                       ; Borro el registro timer 0                                       
    T0CON = %10000111               ; Timer 0 habilitado en modo 8 bit preescaler 256                 
    INTCON2.2=1                     ; Timer 0 de baja prioridad                                       
;-----------------------------------------------------------------------------------------------------------------------------------------------
 
    TRISA       =   %11010000       ; PA0 Reset_LCD, PA1_RS,PA2 CC1, PA3 RW, PA5 CC1                                                               
    TRISB       =   %11111110       ; PORTB 1-7  Entradas de teclado, PB0 salida Teclado                                           
    TRISC       =   %10011000       ; 0: Hab_D1, 1: ENABLE, 2: Hab_D2,3-4: I2C Ent, 5: Sal BKL, 6: Sal Tx , 7: Ent. Rx                                              
    TRISD       =   %00000000       ; Salidas de datos hacia el LCD                                                                 
    TRISE       =   %00000000       ; Puerto E como salidas                                                                         
    INTCON      =   %11111000        ; Configur las interrupciones y la interrupcion del timer0                                     
    PIE1        =   %00000000       
   
    TMR0H = %00010100
    TMR0L = %01010011 
       
    LCD_DTPORT = PORTD       
    LCD_RSPIN = PORTA.1
    LCD_ENPIN = PORTC.1
    LCD_RWPIN = PORTA.3
    LCD_CS1PIN = PORTA.5                                                                                   
    LCD_CS2PIN = PORTA.2
    LCD_TYPE = GRAPHIC
    INTERNAL_FONT = On
    FONT_ADDR = 0
    Declare GLCD_CS_INVERT On
    Declare GLCD_EXTERNAL_PRINT = PPRINT
    CCP1_PIN = PORTC.2
    CCP2_PIN = PORTC.1
    ALL_DIGITAL = True
   
    Symbol  BKL         PORTC.5 


Main:   
        BKL = 0   
        goto main


Interrupcion:
        If intcon.2 = 1 Then
            BKL = 1   
            intcon.2 = 0         
            TMR0H = %00010100
            TMR0L = %01010011
        endif               
        Context Restore
         
End

Si me puede decir cual es el error se lo agradeceria.
Seguire investigando.
Saludos y muchas gracias.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Entendiendo el TIMER0 en CCS
« Respuesta #13 en: 13 de Octubre de 2009, 14:39:49 »
Estas en el subforo equivocado.-
No contesto mensajes privados, las consultas en el foro

Desconectado lopb

  • PIC12
  • **
  • Mensajes: 77
    • contactos lopb
Re: Entendiendo el TIMER0 en CCS
« Respuesta #14 en: 23 de Diciembre de 2010, 11:54:37 »
hola, alquien me puede ayudar?
estoy haciendo un segundero para usar en otras funciones con el timer0 y me esta devolviendo cada 2.x segundos, lo veo en una terminal segun un delay_ms(1000) imprime dos veces lo mismo, a veces 3, entonces estimo que estara en 2 segundos y pico desbordando.
les dejo el codigo a ver si hay algun error. Gracias:
Código: C
  1. #include <18F452.h>
  2. //////// Fuses: LP,XT,HS,RC,EC,EC_IO,H4,RC_IO,PROTECT,NOPROTECT,OSCSEN
  3. //////// Fuses: NOOSCSEN,NOBROWNOUT,BROWNOUT,WDT1,WDT2,WDT4,WDT8,WDT16,WDT32
  4. //////// Fuses: WDT64,WDT128,WDT,NOWDT,BORV20,BORV27,BORV42,BORV45,PUT,NOPUT
  5. //////// Fuses: CCP2C1,CCP2B3,NOSTVREN,STVREN,NODEBUG,DEBUG,NOLVP,LVP,WRT
  6. //////// Fuses: NOWRT,NOWRTD,WRTD,NOWRTB,WRTB,WRTC,NOWRTC,CPD,NOCPD,CPB
  7. //////// Fuses: NOCPB,EBTR,NOEBTR,EBTRB,NOEBTRB
  8. #FUSES NOWDT                    //No Watch Dog Timer
  9. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  10. #FUSES NOPUT                    //No Power Up Timer
  11. #FUSES NOPROTECT                //Code not protected from reading
  12. #FUSES NODEBUG                  //No Debug mode for ICD
  13. #FUSES NOBROWNOUT               //No brownout reset
  14. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  15. #FUSES NOCPD                    //No EE protection
  16. #FUSES NOWRT                    //Program memory not write protected
  17. #FUSES NOOSCSEN
  18. #FUSES NOPUT
  19. #FUSES CCP2C1
  20. #FUSES NOSTVREN
  21. #FUSES NODEBUG
  22. #FUSES NOWRTD
  23. #FUSES NOWRTB
  24. #FUSES NOWRTC
  25. #FUSES NOCPB
  26. #FUSES NOEBTR
  27. #FUSES NOEBTRB
  28.  
  29. #use delay(clock = 20000000)
  30. #use rs232 (baud=9600,xmit=PIN_C6,rcv=PIN_C7)
  31.  
  32. unsigned int16 seconds = 0;
  33.  
  34. #INT_RTCC                                    //Interrupt procedure
  35. clock_isr() {                                //called every time RTCC
  36. set_timer0(19531);
  37.       ++seconds;   //Inc SECONDS counter every
  38.                                            //76 times to keep time
  39. }
  40.  
  41. void main() {                                //a simple stopwatch program
  42.  
  43.    setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 );
  44.    set_timer0(19531);
  45.    enable_interrupts(INT_RTCC);
  46.    enable_interrupts(GLOBAL);
  47.  
  48.    do {
  49.       delay_ms(1000);
  50.       printf("%lu seconds \n\r", seconds);
  51.    } while (TRUE);
  52. }


 

anything