Autor Tema: Problema con Timer1 32.768KHZ  (Leído 3079 veces)

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

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Problema con Timer1 32.768KHZ
« en: 12 de Enero de 2017, 12:43:05 »
Muy buenas a tod@s!

Estoy haciendo un proyecto en el que pretendo contar horas minutos y segundos. Por eso utilizo un PIC16F1825 con una frecuencia interna de 4Mhz. Para contar los segundos utilizo un cristal oscilador de 32.768Khz puesto entre OSC1 i OSC2 (Timer1). Estoy programando con MPLABX y ayudandome del MCC (code configurator) y no hay manera que funcione. Alguien me puede arrojar un poco de luz sobre el tema? Os paso el trozo de codigo con las configuraciones, a ver si hay algo que estoy haciendo mal:

Código: [Seleccionar]

#pragma config FOSC = LP    // Oscillator Selection->LP Oscillator, Low-power crystal connected between OSC1 and OSC2 pins
#pragma config WDTE = OFF    // Watchdog Timer Enable->WDT disabled
#pragma config PWRTE = OFF    // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF    // MCLR Pin Function Select->MCLR/VPP pin function is digital input
#pragma config CP = OFF    // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF    // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = OFF    // Brown-out Reset Enable->Brown-out Reset disabled
#pragma config CLKOUTEN = OFF    // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = OFF    // Internal/External Switchover->Internal/External Switchover mode is disabled
#pragma config FCMEN = OFF    // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is disabled

// CONFIG2
#pragma config WRT = OFF    // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = OFF    // PLL Enable->4x PLL disabled
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF 

void OSCILLATOR_Initialize(void)
{
   
    OSCCON = 0x6A;
    // TUN 0;
    OSCTUNE = 0x00;
    // Set the secondary oscillator
   
    TRISA4 = 1;        // timer-1 osc
    TRISA5 = 1; // timer-1 osc
    TMR1H  = 0x00;           // initially  timer to count 00
    TMR1L  = 0x00;
    T1CON  = 0x00;
    T1GCON = 0;             // Timer 1 Gate function disabled
   
   
    TMR1IF = 0;               // Clear any pending Timer 1 interrupt indication TMR1IE = 1;

    TMR1ON = 0;

    PEIE=1;     //Enable Peripheral Interrupt

}

void TMR1_Initialize(void)
{
    //Set the Timer to the options selected in the GUI
    //T1CKPS 1:8; T1OSCEN enabled; nT1SYNC do_not_synchronize; TMR1CS External; TMR1ON off;
    T1CON = 0x89;
  //T1GSS T1G; TMR1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled;
    T1GCON = 0x00;

    TMR1H = 0x80;           // 1 second
    TMR1L = 0x00;

    // Load the TMR value to reload variable
    timer1ReloadVal=(TMR1H << 8) | TMR1L;


    T1GCON = 0;             // Timer 1 Gate function disabled
    TMR1IF = 0;               // Clear any pending Timer 1 interrupt indication
    TMR1IE = 1;              // Enable Timer 1 interrupt

   
     // Clearing IF flag before enabling the interrupt.
    PIR1bits.TMR1IF = 0;

    // Enabling TMR1 interrupt.
    PIE1bits.TMR1IE = 1;
    // Set Default Interrupt Handler
   // TMR1_SetInterruptHandler(TMR1_DefaultInterruptHandler);
}

void PIN_MANAGER_Initialize(void)
{
    /**
    LATx registers
    */   
    LATA = 0x00;   
    LATC = 0x00;   

    /**
    TRISx registers
    */   
    TRISA = 0x3E;
    TRISC = 0x1F;

    /**
    ANSELx registers
    */   
    ANSELC = 0x00;
    ANSELA = 0x14;

    /**
    WPUx registers
    */
    WPUA = 0x04;
    WPUC = 0x00;
    OPTION_REGbits.nWPUEN = 0;

    /**
    APFCONx registers
    */
    APFCON1 = 0x00;
    APFCON0 = 0x00;

}

void WDT_Initialize(void)
{
    // WDTPS 1:65536; SWDTEN OFF;
    WDTCON = 0x16;
}

void SYSTEM_Initialize(void)
{
   
    PIN_MANAGER_Initialize();
    OSCILLATOR_Initialize();
    WDT_Initialize();
    TMR1_Initialize();
}


El clock tiene sus pertinentes condensadores de 22pF a masa.

Espero que alguien pueda ayudarme. Gracias de antemano!  ;-)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con Timer1 32.768KHZ
« Respuesta #1 en: 12 de Enero de 2017, 15:32:22 »
Como comparten pines el T1OSC y el OSC1, creo que deberias usar el oscilador interno en 4Mhz, y luego si habilitas solo desde el timer el oscilador para esos pines.
Lo digo porque veo que haces:

Citar
#pragma config FOSC = LP    // Oscillator Selection->LP Oscillator, Low-power crystal connected between OSC1 and OSC2 pins

Ponelo como interno ahi. Con respecto al codigo.. no se por que modificas valores y luego lo volves a cargar. El oscilador del TMR1 hay que "esperarlo" que se estabilize. La parte del oscilador seria esto, no tenes que activar interrupciones y limpiar flag del Timer aca, si eso es del timer.

Código: C
  1. void OSCILLATOR_Initialize(void)
  2. {
  3.     while(!OSCSTAbits.HFIOFL);          // HFIOFL bit, oscilador HF estable?
  4.  
  5.     OSCCON = 0x6A;                      // 4Mhz IOSC
  6.  
  7.  
  8.     // Set the secondary oscillator
  9.    
  10.     T1CON = 0x08                        // Activo oscilador
  11.  
  12.     while(!OSCSTAbits.T1OSCR);          // T1OSCR bit, oscilador TMR1 estable?
  13.  
  14. }

Ya tengo el oscilador ahora el timer,, no se por que habia 2 instrucciones con lo mismo

Código: C
  1. void TMR1_Initialize(void)
  2. {
  3.     //Set the Timer to the options selected in the GUI
  4.     //T1CKPS 1:8; T1OSCEN enabled; nT1SYNC do_not_synchronize; TMR1CS External; TMR1ON off;
  5.  
  6.     T1CONbits.TMR1CS = 0b10;            // OSC externo
  7.     T1CONbits.T1CKPS = 0b11;            // 1/8
  8.     T1CONbits.TMRON = 1;                // Activo
  9.  
  10.     //T1GSS T1G; TMR1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled;
  11.     T1GCON = 0x00;
  12.  
  13.     TMR1 = 0x8000;           // 1 second
  14.  
  15.     // Load the TMR value to reload variable
  16.     timer1ReloadVal=(TMR1H << 8) | TMR1L;
  17.  
  18.      // Clearing IF flag before enabling the interrupt.
  19.     PIR1bits.TMR1IF = 0;
  20.  
  21.     // Enabling TMR1 interrupt.
  22.     PIE1bits.TMR1IE = 1;
  23.  
  24.     // Set Default Interrupt Handler
  25.    // TMR1_SetInterruptHandler(TMR1_DefaultInterruptHandler);
  26. }

Por los comentarios, parece que lo hubieras sacado de otro lado. Tenes una inicializacion del WDT y lo tenes desactivado.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #2 en: 13 de Enero de 2017, 04:35:46 »
Gracias KILLERJC!

No lo he sacado de ningún lado, lo que pasa es que me he ayudado del Code composer y aunque no tengo activado el WDT el code composer te crea ese trozo de código igualmente aunque realmente no va a hacer nada. Si hay cosas repetidas es porque hice mil y una pruebas sin ningún resultado y al final pues puede ser que haya código redundante. Si ves que hay un poco de lío en el código es por eso porque ya anteriormente hice pruebas y algo se quedó por allí, como lo del LP que después de colgar el código ya lo modifiqué a INTOSC. Ya sabia que tienes que esperar a estabilizar el clock pero no sabia como hacerlo. Intenté mirar el bit OSTS del byte OSCSTAT porque creo que es la bandera que indica cuando el clock está listo pero no dio muy buen resultado. 

Muchas gracias por tu respuesta! Ahora mismo voy a probar esto a ver si ahora si.  :)

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #3 en: 16 de Enero de 2017, 05:31:18 »
Ahora el cristal responde, se activa y cuenta segundos! ya es todo un logro!!

Aún así, sigo teniendo problemas... No soy capaz de contar cada segundo... tiene un error de 2 segundos por minuto y no se que configuración debo programar para que cuente sin errores.

Adjunto la configuración. He modificado alguna cosa para que funcione con MPLABX:


Código: [Seleccionar]
// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF    // Watchdog Timer Enable->WDT disabled
#pragma config PWRTE = ON    // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF    // MCLR Pin Function Select->MCLR/VPP pin function is digital input
#pragma config CP = OFF    // Flash Program Memory Code Protection->Program memory code protection is disabled
#pragma config CPD = OFF    // Data Memory Code Protection->Data memory code protection is disabled
#pragma config BOREN = OFF    // Brown-out Reset Enable->Brown-out Reset disabled
#pragma config CLKOUTEN = ON    // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
#pragma config IESO = OFF    // Internal/External Switchover->Internal/External Switchover mode is disabled
#pragma config FCMEN = OFF    // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is disabled

// CONFIG2
#pragma config WRT = OFF    // Flash Memory Self-Write Protection->Write protection off
#pragma config PLLEN = OFF    // PLL Enable->4x PLL disabled
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
#pragma config LVP = OFF    // Low-Voltage Programming Enable->High-voltage on MCLR/VPP must be used for programming




Código: [Seleccionar]

void PIN_MANAGER_Initialize(void)
{
    /**
    LATx registers
    */   
    LATA = 0x00;   
    LATC = 0x00;   

    /**
    TRISx registers
    */   
    TRISA = 0x3E;
    TRISC = 0x1F;

    /**
    ANSELx registers
    */   
    ANSELC = 0x00;
    ANSELA = 0x04;

    /**
    WPUx registers
    */
    WPUA = 0x04;
    WPUC = 0x00;
    OPTION_REGbits.nWPUEN = 0;

   
    /**
    APFCONx registers
    */
    APFCON1 = 0x00;
    APFCON0 = 0x00;

    /**
    IOCx registers
    */
    // interrupt on change for group IOCAF - flag
    IOCAFbits.IOCAF4 = 0;
    // interrupt on change for group IOCAN - negative
    IOCANbits.IOCAN4 = 0;
    // interrupt on change for group IOCAP - positive
    IOCAPbits.IOCAP4 = 0;

    // register default IOC callback functions at runtime; use these methods to register a custom function
    IOCAF4_SetInterruptHandler(IOCAF4_DefaultInterruptHandler);
   
   
}


Código: [Seleccionar]
void SYSTEM_Initialize(void)
{
    PIN_MANAGER_Initialize();
    OSCILLATOR_Initialize();
    WDT_Initialize();
    TMR1_Initialize();
}

void OSCILLATOR_Initialize(void)
{   
    OSCCON = 0x6A;                      // 4Mhz IOSC
    while(!HFIOFL);          // T1OSCR bit, oscilador TMR1 estable?
    // Set the secondary oscillator
     T1CON = 0x8C;                        // Activo oscilador
    //OSCSTATbits_t.HFIOFL
    while(!T1OSCR);
}

void TMR1_Initialize(void)
{
    //Set the Timer to the options selected in the GUI
    //T1CKPS 1:1; T1OSCEN enabled; nT1SYNC synchronize; TMR1CS External; TMR1ON off;

   T1CONbits.T1CKPS = 0b11;
   T1CONbits.TMR1CS = 0b10;            // OSC externo
    //T1GSS T1G; TMR1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled;
    T1GCON = 0x00;
    TMR1H = 0x00;
    TMR1L = 0x00;

    // Load the TMR value to reload variable
    timer1ReloadVal=(TMR1H << 8) | TMR1L;
 
     // Clearing IF flag before enabling the interrupt.
    PIR1bits.TMR1IF = 0;
    // Enabling TMR1 interrupt.
    PIE1bits.TMR1IE = 1;
    // Set Default Interrupt Handler
    TMR1_SetInterruptHandler(TMR1_DefaultInterruptHandler);
    // Start TMR1
    TMR1_StartTimer();
}

void TMR1_StartTimer(void)
{
    // Start the Timer by writing to TMRxON bit
    T1CONbits.TMR1ON = 1;
}




Alguna ayuda? Gracias!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con Timer1 32.768KHZ
« Respuesta #4 en: 16 de Enero de 2017, 14:29:13 »
Lo primero que haria es utilizar el modulo CCP de esa forma es menor el "delay" entre que se pone el valor en el timer1 ya que se hace por hardware. Si aun asi eso no te da un valor razonable pero tal ves en el dia tengas alguna variacion, miraria tambien que se cumpla todo el circuito necesario que necesita el cristal (capacidades correctas, carcaza a GND, anillo de GND alrededor de todo el circuito), ya con eso deberias eliminar la mayoria de los errores excepto el del mismo cristal, entonces ya ahi pensaria en utilizar algun mejor cristal.

Si no te interesa tanto podrias buscar algun RTCC y comunicarte con el PIC a este. Ademas estos vienen preparados para usar una bateria que sigue mantiniendo la cuenta.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #5 en: 16 de Enero de 2017, 14:43:24 »
Gracias KILLERJC! Intentaré esa solución, a ver si así consigo algo porque esos 2 segundos de mas me están desesperando...  En cuanto tenga resultados comento.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #6 en: 19 de Enero de 2017, 09:38:45 »
Parece que ya he medio resuelto el problema!!

Buscando mas profundamente por el datasheet del microcontrolador (lectura nocturna recomendable para dormirte rapido) he encontrado el registro OSCTUNE que se encarga de ajustar la configuración del oscilador secundario. Se puede ajustar entre los valores 20h y 1Fh y por defecto esta a 0. Lo he ajustado a 1F y funciona! ahora 1 segundo es 1 segundo. Haré un test de 24 o 12 horas a ver que tal...  Gracias por la ayuda!

Código: [Seleccionar]
OSCTUNE = 0x1F; //The default value of the OSCTUNE register is ‘0’. The
                    //value is a 6-bit two’s complement number. A value of
                    //1Fh will provide an adjustment to the maximum
                    //frequency. A value of 20h will provide an adjustment to
                    //the minimum frequency

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con Timer1 32.768KHZ
« Respuesta #7 en: 19 de Enero de 2017, 09:46:23 »
OSCTUNE solo modifica la frecuencia de HFINTOSC y MFINTOSC , pero no LFINTOSC, estos son osciladores internos al PIC y no tienen nada que ver con el oscilador del que proviene de los pines externos o Timer1 en este caso.

Tenes que darte cuenta que existe una "sobrecarga" desde que ocurre la interrupcion hasta que asignas el valor nuevamente al timer, ese tiempo es un error.
Mientras que con el CCP en modo Compare, Apenas se detecta la igualdad resetea el Timer1 y comienza a contar de vuelta, todo esto por hardware y no por software, por lo cual el tiempo es menor. Y vos podes atender la interrupcion del CCP en cualquier momento.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #8 en: 19 de Enero de 2017, 11:47:06 »
Ya decía yo que me parecía raro que eso afectase... porque como dices tu los LP no afecta... eso significa que realmente no estoy utilizando el oscilador externo ya que de otro modo la modificación del valor del OSCTUNE no tendría ningún efecto y ahora si lo tiene y considerable.... Probé lo del CCP pero no conseguí que funcionase y por eso intenté lo del OSCTUNE....

Era mas facil programar todo esto con CCS que con MPLABX...

Volveré a intentarlo con el CCP porque tienes razón, mejor algo por Hardware con menos error...

Gracias nuevamente!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con Timer1 32.768KHZ
« Respuesta #9 en: 19 de Enero de 2017, 11:56:38 »
Era mas facil programar todo esto con CCS que con MPLABX...

Y yo ahi difiero, XC8 se acerca mucho mas a lo que es el datasheet.
Pero gustos son gustos, si a vos te parece mas comodo usar CCS usalo, CCS tambien tiene sus cosas que encima serian casi "ocultas" hasta que aprendes que existen.
Mientras que en XC8 hace lo que vos le digas, a pesar que lleva mas tiempo por no tener funciones pre-armadas como CCS. De todas formas recalco nuevamente lo que esta en negrita.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #10 en: 19 de Enero de 2017, 12:18:58 »
A ver, me gusta mas XC8 en general también porque es lo que comentas que es mas el datasheet puro, puedes tocar el microcontrolador a tu aire y eso me gusta. Lo bueno del CCS por contra es que te da muchas cosas pre-configuradas o casi hechas y, por tanto, algo mas fáciles de programar en algunos casos y en concreto el tema de los timer y osciladores era mas sencillo de configurar con CCS.

A veces XC8 puede ser un poco desesperante cuando inicias algún modulo que no has tocado nunca o las configuraciones, al menos para mi, aunque después el resultado es mas gratificante porque sabes exactamente que has configurado y como lo has hecho y en CCS no siempre es así.

Con CCS un software parecido ya lo hice, pero quiero lograrlo con XC8 porque quiero usarlo en todos los proyectos a partir de ahora.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con Timer1 32.768KHZ
« Respuesta #11 en: 19 de Enero de 2017, 12:31:45 »
A veces XC8 puede ser un poco desesperante cuando inicias algún modulo que no has tocado nunca o las configuraciones, al menos para mi, aunque después el resultado es mas gratificante porque sabes exactamente que has configurado y como lo has hecho y en CCS no siempre es así.

Yo no lo veo como desesperante, es desesperante si vas sin prepararte o sin haber leido nada.

Tal cual hacia en yo en ASM, lo primero que haces es ir y leer el modulo para tener una idea de como funciona, por mas que tengas funciones pre-configuradas si no sabes como funciona es lo mismo, ya que no vas a saber que valores poner/cargar sino.
Y luego en XC8 simplemente revisas todos los registros que usa ese modulo, eso lo haces mirando al final del capitulo del modulo donde tenes todos los bits y registros involucrados.
Finalmente revisas cada registro para ver que es cada bit, configuras cada uno sea necesario y con eso tenes tu modulo funcionando. Sea cual sea el modulo.

En si...

- Conoces como funciona el CCP? Aunque sea en modo compare? SI: vas y ves todos los registros involucrados, NO: Lees aunque sea esa parte y entendes el diagrama que te da del modulo.
- Como configuro el CCP? Sabiendo que registros y bits actuan sobre el CCP, busco la descripcion del registro y modifico los mismos.

Lo mismo se aplica para el timer.
Al menos ese es el proceso que yo realizo, luego con el tiempo podes saltarte algunos e ir directamente a los registros que te interesan.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #12 en: 19 de Enero de 2017, 12:51:02 »
Claro, es así como se debe proceder y como procedo pero hay veces que por mas que mires el datasheet hay algunas configuraciones que o no salen como quieres o donde te quedas encallado (me pasó por ejemplo en una pantalla TFT muy especifica donde me costó días averiguar que valor de frecuencia debía configurar y saber que era necesario poner unos delays... o con las tarjetas SD... también me llevó un poco detiempo... Al menos para mí, a veces, aunque vayas preparado puedes encontrarte con cosas que te pueden llegar a desesperar un poco. Es como este caso del Timer... en principio, según Microchip y el datasheet del PIC tenia las configuraciones adecuadas y aún así no hace lo que yo espero que haga. Seguramente será que no estoy suficientemente preparado para ello por eso me releo el datasheet a menudo. Una vez ya has trabajado con un modulo es lo que dices ya vas directamente a lo que te interesa.

Aún me falta por aprender! suerte de este tipo de foros!

Probaré lo del CCP y releeré todo el Timer a ver si logro encontrar donde lo estoy haciendo mal.

Desconectado f-traxx

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 116
Re:Problema con Timer1 32.768KHZ
« Respuesta #13 en: 26 de Enero de 2017, 14:12:04 »
Al final, después de muchas pruebas... vi que cuando configuro el PIC para funcionar con oscilador externo, no funciona nada del TMR1... así que deduzco que no funciona el circuito aunque lo he montado todo siguiendo las indicaciones de MICROCHIP. Puede ser que este PIC tenga un Bug en esta parte? porque he probado lo mismo en un 18F4550 y sí funciona.... Al final opté por utilizar timer 1 interno.

Muchas gracias por la ayuda y los consejos!

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problema con Timer1 32.768KHZ
« Respuesta #14 en: 26 de Enero de 2017, 18:18:27 »