Skip to content

Real Time Clock (RTC) ICs

Published On:
Jan 25, 2024
Last Updated:
Sep 20, 2024

Real-Time Clock (RTC) ICs are chips which accurately track calender time. They are generally designed for low-power operation so that they can run of a small battery such as a coin cell. They are normally included on circuits and connected to a microcontroller when the application requires the microcontroller to keep track of time. They are better at keeping track of time than the MCUs internal oscillator due to:

  1. Increased time keeping accuracy. Even when the MCU also has a 32.768kHz crystal, a dedicated RTC is normally more accurate due the ability on many RTCs to tune/calibrate the frequency.
  2. Very low power operation. When a RTC is powered of a small battery like a coin cell it will continue running for many years and will not lose track of time when the MCU is unpowered.

RTCs normally keep track of either UNIX time (or any arbitrary start point you choose) and/or calender based time variables, which are also referred to as broken-down time1. The broken-down time is normally represented by:

  • Second of minute (a value in the range [0-59])
  • Minute of hour (a value in the range [0-59])
  • Hour of day (a value in the range [0-23])
  • Day of month (a value in the range [0-31])
  • Day of the week (e.g. Sunday, Monday, …, normally represented by an integer in the range [0, 6])
  • Month (a value in the range [1-12])
  • Year (e.g. 2023, 2024, …)

It is called broken-down time due to the time not being a single monotonic count of some unit like UNIX time (which is the number of seconds elapsed since 00:00:00 UTC on Jan 1st, 1970), but broken down into days/months/years.

It’s worth noting that even though you can calculate the day of the week from the day/month/year, most RTCs let you store it as a separate variable for convenience (so you don’t have to keep recalculating it). If you do need to calculate it, below is some C code you can use to calculate the day of the week from the day/month/year2.

/**
* Calculate the day of the week given the year, month and day. Accurate for any Gregorian date.
* Taken from https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week.
*
* @param[in] y Year in the format YYYY, e.g. 2024.
* @param[in] m Month in the range [1, 12], e.g. 9 for September.
* @param[in] d Day in the range [1, 31], e.g. 20.
* @return Day of the week in the range [0, 6], where 0 is Sunday, 1 is Monday, etc.
*/
uint8_t CalcDayOfWeek(uint16_t y, uint8_t m, uint8_t d) /* 1 <= m <= 12, y > 1752 (in the U.K.) */
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
if(m < 3)
{
y -= 1;
}
return (y + y/4 - y/100 + y/400 + t[m - 1] + d) % 7;
}

For example, CalcDayOfWeek(2024, 9, 20) would return 5 which is a Friday.

Conversion Between UNIX Time and Calender Time

The following C code shows how to convert to/from UNIX time and calender time, which can be useful when dealing with RTCs in firmware:

#include <stdio.h>
#include <time.h>
int main(void) {
// UNIX time for Thu Jan 25 01:00:33 2024 UTC
time_t unixTime = 1706144433;
printf("Starting with UNIX time of %ld\n", unixTime);
// Storage to hold converter calender time
struct tm utcCalenderTime;
// Do the conversion
gmtime_r(&unixTime, &utcCalenderTime);
// Print conversion. asctime() converts the calender time into a string for us
printf("Converted calender time: %s", asctime(&utcCalenderTime));
// Convert back from calender time to UNIX time just for fun
time_t unixTime2 = mktime(&utcCalenderTime);
printf("Converted UNIX time: %ld\n", unixTime2);
return 0;
}

You can run this example at https://replit.com/@gbmhunter/c-unix-time-to-calender-time.

Examples

NXP PCF85263A

The NXP PCF85263A is a low-power I2C controlled RTC3. It has separate pins for system power supply VDD and battery VBAT, switching over to VBAT automatically when system power is lost.

The below image shows the block diagram for this IC. You can see the pins that connect to an external 32.768kHz oscillator in the bottom left corner.

The block diagram for the NXP PCF85263A RTC3.

The time-based values (100ths of a second, seconds, minutes, hours, days, months, years) are all stored in Binary Coded Decimal (BCD) format (each group of 4 bits represents a number in the range [0, 9]). To prevent time values updating mid-read and producing inconsistent results, all time registers are frozen during reads over the I2C.

It automatically handles leap years correctly (which are deterministic and apply to all time zones). It does not handle day light saving (depends on the time zone), nor leap seconds (not deterministic).

The PCF85263A has an offset register that can be used to dynamically make small adjustments to the period of a second, so it can be used for things such as tuning/calibration and temperature compensation. It also supports a number of different quartz crystal types, including crystals that need a load capacitance of 6.0pF, 7.0pF, and 12.5pF.

Firmware Support

The RTOS and peripheral API framework that Zephyr provides defines a RTC API (interface)4. There are simple methods such as rtc_set_time() and rtc_get_time(). The API also provides methods to set alarms (e.g. rtc_alarm_set_time()), callbacks to be called when alarms are triggered, and functions to calibrate the RTC.

Footnotes

  1. Zephyr (2024, Jan 25). Real-Time Clock (RTC) [API documentation]. Retrieved 2024-01-25, from https://docs.zephyrproject.org/latest/hardware/peripherals/rtc.html.

  2. Wikipedia (2024, Sep 7). Determination of the day of the week. Retrieved 2024-09-20, from https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week.

  3. NXP (2023, Nov 22). PCF85263A - Tiny RTC/calendar with alarm function, battery switch-over, time stamp input, and I2C-bus [datasheet]. Retrieved 2024-01-25, from https://www.nxp.com/docs/en/data-sheet/PCF85263A.pdf. 2

  4. Zephyr. RTC Interface. Retrieved 2024-09-20, from https://docs.zephyrproject.org/latest/doxygen/html/group__rtc__interface.html.