⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtc.c

📁 TDK 6521 SOC 芯片 DEMO程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
 * This code and information is provided "as is" without warranty of any   *
 * kind, either expressed or implied, including but not limited to the     *
 * implied warranties of merchantability and/or fitness for a particular   *
 * purpose.                                                                *
 *                                                                         *
 * Copyright (C) 2005 Teridian Semiconductor Corp. All Rights Reserved.    *
 ***************************************************************************/
//**************************************************************************
//  DESCRIPTION: 71M652x POWER METER - Real Time Clock Routines.
// 
//  AUTHOR:  MTF
//
//  HISTORY: See end of file.
//**************************************************************************
// File: RTC.C
//               
#include "options.h"
#include "library.h" // get LRC calculation from the source
#include "meter.h"
#include "freq.h"    // to handle rtc adjustment from line's edge count
#include "lcd.h"
#if TIMERS
#include "stm.h" // use  for timing the write
#elif TMR1
#include "tmr1.h" // timer 1 can be used for timing the write
#elif TMR0
#include "tmr0.h" // timer 1 can be used for timing the write
#elif REAL_TIME_DATE
#error need timers to set the clock
#endif
#include "irq.h"  // interrupt control
#include "rtc.h"  // test the function definitions against the code

#include FILE_DEFINING_RTC

#if  OPERATING_TIME
// display the number of hours of operation
void operating_lcd (void)
{
    LCD_Number_Max (OperatingSeconds / 36, 2);  // Display max digits.
    LCD_2DP ();                                 // Two decimal places.
}
#endif

#if  REAL_TIME_DATE
/*** External functions referenced by this module ***/
// See includes

/*** External variables referenced by this module ***/
// Options.h must define:
// RTC_COPY, a structure in xdata RAM of type RTC_t that contains the 
// system's clock variables.  The demo code, defines RTC_COPY in options_gbl.h
// In the demo code, RTC_COPY is near the other meter data, in
// the data structure "Totals", defined in meter.h
// Some compensation data might also be needed: slow, trim, and trim_count
// These are nonvolatile because they are used to compensate the clock for 
// the time the unit was off.  SInce they're nonvolatile, they need to be
// in the nonvolatile memory.
// If COMPENSATION is nonzero, enabling temperature compensation, options.h
// must also somehow define:
// Y_Cal_Deg2 is   1 ppb =>   1 Y_Cal_Deg2 is 1 ppb.
// Y_Cal_Deg1 is  10 ppb =>  10 Y_Cal_Deg1 is 1 ppb.
// Y_Cal_Deg0 is 100 ppb => 100 Y_Cal_Deg0 is 1 ppb.
// In the demo code, these are in the "Parameter_t" section of Totals, 
// defined in meter.h


/*** Public functions declared within this module ***/
// See "rtc.h".

/*** Public variables declared within this module ***/
// rtc_ready, a bool set once per second by the isr.

/*** Private functions declared within this module ***/
static void RTClk_Write_Delay (void) small reentrant;

/*** Private variables declared within this module ***/
volatile bool rtc_ready;
static volatile bool rtc_adjusting_now;
static volatile uint8x_t RTC_idx = 0;


// display the date on the LCD
void date_lcd (void)
{
	LCD_Command (LCD_CLEAR);
	LCD_Year  (RTC_COPY.Year);
	LCD_Month (RTC_COPY.Month);
    LCD_Date  (RTC_COPY.Date);
}

// display the time on the LCD
void time_lcd (void)
{
	LCD_Command (LCD_CLEAR);
	LCD_Hour(RTC_COPY.Hour); 
	LCD_Min (RTC_COPY.Min);
	LCD_Sec (RTC_COPY.Sec);
}

void RTClk_Reset (void)                    // Reset RTC to defaults, if necessary.
{
    #if !RTC_LINE_LOCKED // if it's line-locked, don't do compensation
    struct RTC_t xdata rtc_temp;
    
    // save the last valid clock reading
    memcpy_xx((uint8x_t*)&rtc_temp, (uint8x_t*)&RTC_COPY, sizeof(RTC_COPY));
    #endif

    RTClk_Read ();
    if (RTC_COPY.Year == 0) // has the clock been set since it was first powered?
    {
        // Power to the clock failed, so set it. 
        // This could copy the last saved date and time, but that could 
        // cause the mistaken belief that the clock was "losing time" when the battery was bad.
        memset_x ((uint8x_t *) &RTC_COPY, 0x01, sizeof (RTC_COPY));
        RTClk_Write ();
        #if !RTC_LINE_LOCKED // if it's line-locked, don't do compensation
        trim_count = 0; // restart the trimming
        second_count = 0;
        #endif
        Status |= CLOCK_UNSET;
    }
    #if !RTC_LINE_LOCKED // if it's line-locked, don't do compensation
    // It needs to know how long the power was off.
    if (0 != ((POWER_BAD | CLOCK_UNSET) & Status))
    {
        // Either the last running date, or the current time is bad
        // Also, the trim was not saved, so it needs to be recalculated.
        #if RTC_COMPENSATION
        // deltaT, the difference in temperature from the calibration
        // temperature, is cleared to zero at start-up, so it stays zero
        // until it is measured. The constant drift (Y-Cal_Deg0) runs
        // right away, though.
        RTC_Compensation ();             // Calculate compensation of RTC.   
        #else
        // if no other clock compensation,
        // calculate a constant clock drift
        trim_value = (int32_t) (Y_Cal_Deg0 * 100L);
        #endif
    }
    else
    {
        // Compensate for the time off by simulating the normal adjustment.
        // It uses the last valid trim, which was collected when
        // the temperature was running, more accurate than
        // the trim for the calibration temperature.
        // Multiplication must be used, rather than a loop, because
        // the unit could be unpowered for millions of seconds while in
        // storage.
        float delta_trim = (float)Delta_Seconds (&rtc_temp, &RTC_COPY);
        int16_t seconds;

        irq_disable();
        delta_trim = (delta_trim * (float)trim_value) + (float)trim_count;
        seconds = (int16_t)(delta_trim / 1.0e9);
        second_count += seconds;
        trim_count = (int32_t)(delta_trim - (1.0e9 * ((float)seconds)));
        irq_enable();
    } 
    #endif
    RTC_idx = 0;
}

void RTClk_Write (void)
{
    RTC_idx = sizeof(RTC)-1;    
    RTClk_Write_Delay ();
}


#if CE_OFF
bool RTC_Tic (void)                        // called to detect a 1-second tick.
{
    if (rtc_ready)
    {
       rtc_ready = FALSE;
       return (TRUE);
    }
    else
       return (FALSE);
}
#endif // ce_off

#pragma save
#pragma NOAREGS
static void RTClk_Write_Delay (void) small reentrant
{
    #if M6520
    WE = 0x00;                            // Write Enable RTC.
    #endif

    RTC[ RTC_idx ] = *(RTC_idx + ((uint8x_t*)&RTC_COPY));

    // keep it from overwriting I/O
    if (RTC_idx > 0)
    {
       // Switched to software timers to use less code, and free a timer.
       // The two is the minimum reliable number of clock ticks.
       #if TIMERS
       if(NULL != stm_start (2, 0, RTClk_Write_Delay))
           --RTC_idx;
       else
           RTC_idx = 0;
       #elif TMR0 || TMR1
       // 397us = 13/32768 of a second, the minimum time to write
       tmr_start (microseconds2tmr_reg(500), 0, RTClk_Write_Delay);
       --RTC_idx;
       #else
       #error need a timer
       #endif
    }
}
#pragma restore

void RTClk_Read (void)
{
    uint8_t xdata sec;
    uint8_t xdata old_sec;

    if(RTC_idx != 0)
        return;

    sec = -1;
    do
    {
       old_sec = sec;
       sec = RTC[ 0 ];
    } while (sec != old_sec);

    memcpy_xx ((uint8x_t *) &RTC_COPY, RTC, sizeof (RTC));    
}

#if RTC_COMPENSATION
// This is the RTC's temperature compensation.  It's updated in run_meter()
// in meter.c, running each time the meter measures the temperature.
// It figures the clock's compensation in parts per billion.
// Y_FREQ = XTAL_FREQ * {[Y_DEG2 * deltaT + Y_DEG1] * deltaT + Y_CAL}.      
//
// Y_Cal_Deg2 is   1 ppb =>   1 Y_Cal_Deg2 is 1 ppb.
// Y_Cal_Deg1 is  10 ppb =>  10 Y_Cal_Deg1 is 1 ppb.
// Y_Cal      is 100 ppb => 100 Y_Cal      is 1 ppb.
//
// deltaT     is 0.1 degrees => deltaT / 10 is degrees C.
// 
void RTC_Compensation (void)            // Do temperature compensation of RTC.
{
    int32_t value;

    value = (((((int32_t) Y_Cal_Deg2 * deltaT) / 100 + (int32_t) Y_Cal_Deg1) * deltaT) + (int32_t) Y_Cal_Deg0 * 100);

    RTC_Adjust_Trim (FALSE, value);
}

void RTC_Adjust_Trim (bool clr_cnt, int32_t value)
{
    irq_disable();                     // Begin critical section.

    // using a signed value means that opposite signs cancel, as they should
    trim_value = value;

    if (clr_cnt)
    {
        trim_count = 0;
        second_count = 0;
    }

    irq_enable();                      // End critical section.
}
#endif // RTC_COMPENSATION.

#if !RTC_LINE_LOCKED
// time since midnight, january 1, 2000
int32_t Julian (struct RTC_t xdata *ptm)
{
    int32_t a, y, m, j;
    a = (14 - (*ptm).Month) / 12L;
    y = (int32_t)(*ptm).Year + 6800L - a;
    m = (int32_t)(*ptm).Month + (12 * a) - 3;
    // julian days since Jan 1, 2000; 5.8e6 years range in 32-bit signed no.
    j = (int32_t)(*ptm).Date 
        + (((153 * m) + 2)/5)
        + (365 * y)
        + (y / 4)
        - (y / 100)
        + (y / 400)
        - 2483590;
    #if 1
    // julian seconds... 68 years range in a 32-bit signed number
    j = (j * 86400) 
         + (((int32_t) (*ptm).Hour - 12) * 3600)
         + ((int32_t) (*ptm).Min * 60)
         + (int32_t) (*ptm).Sec;
    #elif 0
    // julian millihours... 244 years range in a 32-bit signed number
    j = (((j * 24) + ((int32_t) (*ptm).Hour - 12)) * 1000)
        + ((((int32_t) (*ptm).Min * 50) + 1) / 3)
        + ((((int32_t) (*ptm).Sec * 5) + 9) / 18);
    #elif 0
    // julian decihours... 24,497 years range in a 32-bit signed number
    j = (((j * 24) + ((int32_t)(*ptm).Hour - 12)) * 10)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -