How to convert the value in TSR into real time date and time(and vice versa also) in RTC? Is there any specific alogorithm for these?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

How to convert the value in TSR into real time date and time(and vice versa also) in RTC? Is there any specific alogorithm for these?

3,614 次查看
anand-k
Contributor III

How to convert the value in TSR into real time date and time(and vice versa also) in RTC? Is there any specific alogorithm for these? I am using KL25-FRDM board.

标签 (1)
0 项奖励
回复
7 回复数

2,074 次查看
Monica
Senior Contributor III

Anand, were these suggestions helpful?

Let us know! :smileywink:

Monica

0 项奖励
回复

2,074 次查看
anand-k
Contributor III

Hi Monica,

The reply from Marek was somewhat heplful. But the algorithm and calculations are not quite simple. The above algorithm works only when the starting year is 2000(I made few changes thinking that this algorithm will work when my starting year is 2003;but it doesnt, the calender messed up).

I checked the PE tool to change the starting year as 2003 and I generated the code. There are changes in some lines of the generated code, which were quite difficult to understand(why).

I am looking for an algorithm that is more generic, whatever my starting year is(leap or non-leap ). I dont want to generate code everytime i change my starting year.   

Hope your support will be helping me.

Regards,

Anand

0 项奖励
回复

2,074 次查看
MVa
NXP Employee
NXP Employee

Hi,
  you can use code generated by Processor Expert. See attached project.
 
Best Regards
MVa

/*
** ===================================================================
**     Method      :  RTC1_ConvertSecondsToDateAndTime (component RTC_LDD)
**
**     Description :
**         Computes date and time from the number of seconds till the
**         given date
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static void RTC1_ConvertSecondsToDateAndTime(LDD_RTC_TTime *TimePtr, uint32_t Seconds)
{
  uint32_t x;
  uint32_t Days;

  Days = Seconds / 86400U;             /* Days */
  Seconds = Seconds % 86400U;          /* Seconds left */
  TimePtr->Hour = Seconds / 3600U;     /* Hours */
  Seconds = Seconds % 3600u;           /* Seconds left */
  TimePtr->Minute = Seconds / 60U;     /* Minutes */
  TimePtr->Second = Seconds % 60U;     /* Seconds */
  TimePtr->DayOfWeek = (Days + 6U) % 7U; /* Day of week */
  TimePtr->Year = (4U * (Days / ((4U * 365U) + 1U))) + 2000U; /* Year */
  Days = Days % ((4U * 365U) + 1U);
  if (Days == ((0U * 365U) + 59U)) { /* 59 */
    TimePtr->Day = 29U;
    TimePtr->Month = 2U;
    return;
  } else if (Days > ((0U * 365U) + 59U)) {
    Days--;
  } else {
  }
  x =  Days / 365U;
  TimePtr->Year += x;
  Days -= x * 365U;
  for (x=1U; x <= 12U; x++) {
    if (Days < ULY[x]) {
      TimePtr->Month = x;
      break;
    } else {
      Days -= ULY[x];
    }
  }
  TimePtr->Day = Days + 1U;
}

/*
** ===================================================================
**     Method      :  RTC1_ConvertTimeAndDateToSeconds (component RTC_LDD)
**
**     Description :
**         Computes the number of seconds till the 2000-01-01
**         This method is internal. It is used by Processor Expert only.
** ===================================================================
*/
static LDD_TError RTC1_ConvertTimeAndDateToSeconds(LDD_RTC_TTime *TimePtr, uint32_t *SecondsPtr)
{
  uint32_t Seconds;                    /* Number of seconds till 1.1.2000 */
  if ((TimePtr->Year < 2000U) || (TimePtr->Year > 2099U) || (TimePtr->Month > 12U) || (TimePtr->Month == 0U) || (TimePtr->Day > 31U) || (TimePtr->Day == 0U)) { /* Test correctness of given parameters */
    return ERR_RANGE;                  /* If not correct then error */
  }
  if (TimePtr->Year & 3U) {            /* Is given year un-leap-one? */
    if (ULY[TimePtr->Month] < TimePtr->Day) { /* Does the obtained number of days exceed number of days in the appropriate month & year? */
      return ERR_RANGE;                /* If yes (incorrect date inserted) then error */
    }
  } else {                             /* Is given year leap-one? */

    if (LY[TimePtr->Month] < TimePtr->Day) { /* Does the obtained number of days exceed number of days in the appropriate month & year? */
      return ERR_RANGE;                /* If yes (incorrect date inserted) then error */
    }
  }
  Seconds = ((TimePtr->Year - 2000U) * 365U) + (((TimePtr->Year - 2000U) + 3U) / 4U); /* Compute number of days from 2000 till given year */
  Seconds += MONTH_DAYS[TimePtr->Month]; /* Add number of days till given month */
  Seconds += TimePtr->Day;             /* Add days in given month */
  if ((TimePtr->Year & 3U) || (TimePtr->Month <= 2U)) { /* For un-leap year or month <= 2, decrement day counter */
    Seconds--;
  }
  Seconds = (Seconds * 86400U) + (TimePtr->Hour * 3600U) + (TimePtr->Minute * 60U) + TimePtr->Second;
  *SecondsPtr = Seconds;
  return ERR_OK;
}

0 项奖励
回复

2,074 次查看
LuisCasado
NXP Employee
NXP Employee

Hello,

RTC is a real time counter, not a Real Time Calendar.

You will need to enable Time Seconds Interrupt.

And then in the irq..

seconds++

if(seconds==60) {seconds=0;minute++}

if(minute==60){minute=0;hour++}

if(hour==24){hour=0;day++}

if(day==months_table[month-1]){day=1;month++}

if(month==12){month=1;year++}
etc..

You will have to calculate if leap-year for February in the table

Google source:

To get the Gregorian leap year, simply do not include a leap day in a year divisible by 100 but not divisible by 400. Click Here to view a flow chart that shows how this works..

Probably we have the code in some Reference Design, but I don't recall any. Perhaps someone in the forum can provide the code.

Best Regards,

Luis

0 项奖励
回复

2,074 次查看
anand-k
Contributor III

Hello Luis,

Thanks for your quick reply.

Your answer is straight forward with On Seconds interrupt enabled. Consider like I kept NO RTC interrupt enabled, I initialize(like TSR=0x00, TPR=0x00) and enable/start my RTC. TSR starts incrementing. At some instant later, I want to manipulate real time(date and time) by reading the current counter register TSR. How the algorithm would be?

Could you help me on this?

Thanking you.

0 项奖励
回复

2,074 次查看
LuisCasado
NXP Employee
NXP Employee

Hi,

RTC is a 32 bit timer counting seconds. You can reset the counter by SW, then next time you read, you can calculate the number of second since SW reset, make a new SW reset of counter and calculate H:M:S/YY:MM:DD accordingly. But, you will lose precision, because when you read the second counter, you don't know the fraction of second .2, .7,.. Every time you read the counter, you are losing accuracy in the time.. At least, I don't know other way without using interrupts.

Best Regards,

Luis

0 项奖励
回复

2,074 次查看
Smiffytech
Contributor III

If I understand your question correctly, you want to use a single variable (or register) to store a time/date value.

To do this, you need to define an epoch, so that the variable contains the number of seconds since a certain time/date. The best example of this that comes to mind is UNIX time, which counts seconds since the epoch 1970-01-01 00:00:00Z.  If you wanted to replicate this, you could Google for time.h, and get hold of the corresponding C source to see how the UNIX time functions work.

I believe that there are two disadvantages to using this method in an embedded context:

* You have to perform calculations every time you want to get a timestamp - as opposed to just reading variables, per Luis' example.

* You must make sure that the variable/register (in this case the real time counter) is large enough so that it won't overflow, based on the epoch you choose, and the anticipated liftetime of your hardware. For example, if you were using the UNIX epoch of 1970-01-01 00:00:00, you would need a variable/register big enough to handle the number 1,362,081,470 (the UNIX timestamp when I wrote this paragraph) - which would be a minimum of 32 bits. If my math is correct, you would need 32+ bits to handle any epoch time that needed to work for longer than 6 months.

No matter what method you use to maintain your clock/calendar - whether it is using a single variable/register or using the method suggested by Luis - you need to be mindful of how you will retain the value should the CPU reset. And this is why we have RTC chips! Erich Styger has written about using the DS1307 RTC chip with the Freedom Board: Processor Expert Maxim I2C RTC for the Arduino Data Logger Shield | MCU on Eclipse

0 项奖励
回复