How to make Timer1 more accurate as a real time clock?

不想你离开。 提交于 2020-01-24 19:03:27

问题


I have PIC18F87J11 with 8 MHz oscillator and I am using timer1 as real time clock. At this moment I have it toggle an LED every 1 minute. I noticed it does work perfect fine the first few times but slowly it starts toggling the LED every 59 seconds. Then every few minutes it keeps going down to 58, 57, etc. I don't know if its impossible to get an accurate clock using internal oscillator or if I need external oscillator. My settings look right for timer1, I just hope I can resolve this issue with the current hardware.

Prescaler 1:8, TMR1 Preload = 15536, Actual Interrupt Time : 200 ms

    // Timer 1 Settings
    RCONbits.IPEN = 1; // Enable interrupt system priority feature
    INTCONbits.GIEL = 1; // Enable low priority interrupts
    // 1:8 prescalar
    T1CONbits.T1CKPS1 = 1;
    T1CONbits.T1CKPS0 = 1;
    // Use Internal Clock
    T1CONbits.TMR1CS = 0;
    // Timer1 overflow interrupt
    PIE1bits.TMR1IE = 1;
    IPR1bits.TMR1IP = 0; // Timer 1 -> Low priority interrupt group
    PIE1bits.TMR1IE = 1; // Enable Timer1 interrupt

    // TMR1 Preload = 15536;
    TMR1H = 0x3C;
    TMR1L = 0xB0;

Interrupt Routine

void interrupt low_priority lowISR(void) {
    if (PIR1bits.TMR1IF == 1) {

        oneSecond++;
        if (oneSecond == 5) {

            minute_Counter++; 

            if (minute_Counter >= 60) {
                // One minute passed
                Printf("\r\n One minute Passed");
                ToggleLed();
                minute_Counter = 0;

                            }
        oneSecond = 0;

        }



    // TMR1 Preload = 15536;
    TMR1H = 0x3C;
    TMR1L = 0xB0;

    PIR1bits.TMR1IF = 0;
}}

回答1:


The internal oscillator is a simple RC oscilator (a resistor/capacitor time constant determines its frequency), this kind of circuit may be accurate to only +/-10% over the operating temperature range of the device, and the device will be self-heating due to normal operating power dissipation.

From the data sheet:

An external crystal or other accurate external clock source is required to get accurate timing. Alternatively, if you have some other stable and accurate, but low frequency clock source, such as output from an RTC with a 38768 Hz crystal, you can use that to calibrate the internal RC oscillator and dynamically adjust it with the OSCTUNE register - by using a timer gated by the low frequency source, you can determine the actual frequency of INTOSC and adjust accordingly - it will not be perfect, but it will be better - but no better than the precision of the calibrating source of course.

Some devices have a die temperature sensor that can also be used to compensate, but that is not available on your device.

The RC error can cause serial communications mistiming to the extent that you cannot communicate with a device using asynchronous (UART) serial comms.




回答2:


There are some stuff in the datasheet you linked, "2.5.3 INTERNAL OSCILLATOR OUTPUT FREQUENCY AND TUNING", on p38

The datasheet says that

The INTOSC frequency may drift as VDD or temperature changes".

Are VDD and temperature stable ?

It notes three ways to deal with this by tuning the OSCTUNE register. The three of them would need an external "oscillator" :

  • dealing with errors of EUSART...this signal should come from somewhere.
  • a peripheral clock
  • cpp module in capture mode. You may use any stable AC signal as input.

Good luck !




回答3:


Reload the Timer as soon as it expires, the delay between timer overflow and rearm is affecting the total time. So this will solve your problem.

void interrupt low_priority lowISR(void) 
{
    if (PIR1bits.TMR1IF)
    {
        PIR1bits.TMR1IF = 0;
        TMR1H    = 0x3C;
        TMR1L    = 0xAF;

        /* rest of the code here */
        . . . .
    }
 }

One more recommendation is not to load up the isr, keep it simple.



来源:https://stackoverflow.com/questions/24560793/how-to-make-timer1-more-accurate-as-a-real-time-clock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!