Projects Research & Design Hub

Calibrating an MCU’s RTC Using GPS

Written by Stuart Ball

Put Time on Your Side

Many embedded applications require an accurate real-time clock (RTC). But calibrating an MCU’s internal RTC often requires expensive test instruments and long run times. In this article, Stuart describes how you can use a low-cost GPS module to achieve a good RTC calibration in a short time.

  • How to use a GPS to calibrate an MCU’s internal real-time clock (RTC)

  • Texas Instruments (TI) TM4C Arm MCU

  • ECS XC3158CT, which is a CMOS temperature-compensated oscillator

  • Maxim Integrated DS3234 RTC

  • GPS module

Sometimes a microcontroller (MCU) design needs to track the time accurately. Applications range from periodically waking up the processor from a low-power sleep state, to making measurements or performing some other task. Sometimes you need to maintain time and date, both as part of normal operation and in a backup mode when some other form of time keeping is unavailable.

Most bedside digital clocks are accurate because they use the power line frequency (60Hz in the US) to keep time. Although this frequency can vary throughout the day, it is adjusted to be accurate over a 24-hour period. Many of these clocks have battery backup in case of power failure. I had one several years ago with battery backup, but the one time it lost power, the time was off by several minutes the next morning. The battery backup just wasn’t very accurate.

There are several ways to keep accurate time in an MCU design. They include:

• 60Hz power line
• Add a GPS to the design
• Connect to the Internet
• 60kHz time signal from WWVB

All of these will work, and all have their drawbacks. Your equipment might be in a building where GPS reception is unavailable. You might not have an Internet connection available. Or you may just want to avoid the cost of adding these extra parts to the design to get such timekeeping capability. And even with one of those, you may need a way to maintain accurate time during power outages or loss of connection.

Many MCUs can use a standard 32.768kHz crystal for timekeeping. But calibrating the crystal to maintain accuracy over days or weeks can be a challenge. The 32.768kHz crystal has been around since the earliest electronic watches. It is useful largely because a binary divisor of 32,768 (215) produces a 1Hz output. But, like all crystals, the common 32.768kHz crystal has limited frequency accuracy—typically ±20ppm (parts per million) at room temperature. This means that the frequency of any random crystal may vary from 32,767.3Hz to 32,768.7Hz. This is a tiny change, and for most crystal applications it is not an issue. But for a crystal in an RTC it matters a lot, because any error is cumulative—it adds up over time. There are 604,800 seconds in a week, so a 20ppm error adds up to a timekeeping error of 12 seconds per week. In some applications, this is irrelevant. In others, it’s important.

Figure 1 shows a typical crystal oscillator. For a 32.768kHz crystal, typical values for the capacitors are 10pF to 20pF. U1 is shown as a logic inverter, but it could also be a transistor amplifier or other amplification circuit. In some timekeeping devices, the frequency can be adjusted by making C1 or C2 a variable capacitor, and adjusting it manually.

FIGURE 1 – Simplified schematic of a 32.768kHz oscillator as implemented in an MCU.

Depending on the application, the built-in accuracy of the crystal may be adequate. But in others, more accurate timekeeping is needed. The Texas Instruments (TI) TM4C Arm MCUs have an input for a 32.768kHz crystal, which can be used to drive the RTC. The TM4C parts also include a calibration register to compensate for crystal inaccuracy.

Figure 2 shows a partial block diagram of the TM4C RTC. This diagram illustrates how calibration works, so it doesn’t show every part of the RTC, such as the match registers or power control. The TM4C RTC is part of the hibernation module that includes features such as low-power deep sleep, wake on interrupt, and other features to support low-power operation. For this discussion, only the RTC portion is important.


Advertise Here

FIGURE 2 – Simplified block diagram of the TM4C1233D5’s real-time clock.

The 32.768kHz oscillator drives a 15-bit prescaler that counts 0 to 7FFF to divide by 32,768 (0x8000), producing a 1Hz signal. This signal drives the RTC counter, which is just a 32-bit counter that can be read by the MCU. The RTC counts elapsed seconds, while date and day are calculated in software from the RTC count, if needed.

Every 64 seconds, the contents of the trim register are substituted for the divisor. So, if the trim register contains 0x7FFF, the count is not altered. But if the trim register is set to 0x8004 (0x7FFF + 5), then every 64 seconds the 1Hz output is extended by five periods of the oscillator. The effect is that every 64 seconds, the 1Hz signal is a little longer than normal. This compensates for the variation in the crystal frequency. A trim value less than 0x7FFF results in a shorter period, to compensate for crystals that are below 32.768kHz, and a value greater than 0x7FFF is for crystals that are faster than 32.768kHz.

The schematic of a TM4C1233D5 MCU with a 32.768kHz crystal and a GPS module connected to it is shown in Figure 3. The GPS module is just an inexpensive unit purchased on eBay, with an inexpensive GPS antenna attached (also from eBay). Figure 4 is a photo of the GPS module. The GPS module has a serial interface and a 1PPS (pulse-per-second) output. In this application, only the PPS signal is connected to the TM4C.

FIGURE 3 – Schematic of the TM4C1233D5 circuit used in the article.

FIGURE 4 – Photo of the GPS module used in the article.

Serial port 0—on PA0/PA1 of the TM4C—is used for programming the device and for sending the calibration information to a PC. A jumper, W1, is grounded to put the TM4C into programming mode. J2 is for an external RS-232 converter to connect to the host serial port, as described in my article “Debugging Embedded Systems with Minimal Resources” (Circuit Cellar 312, July 2016) [1]. Figure 5 is a schematic of the programming adapter.

FIGURE 5 – Schematic of the RS-232 converter used to connect the TM4C board to the host PC for downloading firmware and collecting calibration output data.

Although the GPS module is inexpensive, the 1PPS signal from the GPS is accurate, because it is derived from the atomic clock on the GPS satellites. All the expense needed for this accuracy embedded in the satellites is courtesy of American taxpayers. That accuracy is used as the standard for calibrating the RTC on the TM4C.


Advertise Here

The key to this calibration technique is that the divide-by-32,768 prescaler register in the RTC can be read by the CPU. Calibration is performed by counting how many cycles of the crystal oscillator occur in one GPS PPS period. With the trim register set to 0x7FFF, the prescaler divisor in the TM4C is 32,768. The difference in prescaler counts between successive PPS signals indicates the crystal’s accuracy.

The calibration firmware causes the CPU to read the count in the prescaler register every ten PPS signals. The count of 10-second PPS intervals, the RTC register value and the content of the prescaler register are sent to the host via the serial port. You can capture the serial output with a terminal program such as PuTTY. The actual serial port output looks like the following (with header line in bold added above the output to identify the three values):

___PPS________RTC__RTC prescaler
0000.0001: 0009-0000.1A02
0000.0002: 0013-0000.1A24
0000.0003: 001D-0000.1A47
-- Snipped lines for brevity --
0000.0081: 0509-0000.2B57

All values are in hex. Therefore, for the first output, the PPS count is 1 (indicating that ten PPS signals have occurred), the value in the RTC register is 9 and the divisor count is 0x1A02. Ten seconds later, the divisor count is 0x1A24. If the crystal were exactly 32.768kHz, the divisor count would be 1A02 on every output (maybe ±1). But this crystal frequency is high, so the divisor count is running faster than the 1PPS GPS signal, by about 34-35 counts every 10 seconds.

The final output is shown below the first three. By the time 1,280 seconds (0x80 × 10) seconds have elapsed, the divisor count is 0x2B57. The total difference is 0x2B57 – 0x1A02 (11,095-6,658), or 4,437 counts in 1,280 seconds. In reality, it could be very close to 4,436 (11,095.0 – 6,658.99) or 4,438 (11,095.99 – 6,658.0), but 4,437 is as close as we can get.


Advertise Here

Each divisor count is 1 cycle of the 32.768kHz clock, so the total error is 4,437/1,280 or 3.46 cycles per second. This means the crystal is really operating at about 32,771.46Hz. This is an error of 3.46/32768 × 106 or 105.7ppm. This is just a generic crystal so I don’t have the specifications for it, but it’s probably a 100ppm part. It’s also possible that the 15pF capacitors are the wrong value for the part, although the TM4C1233D5 specifies a minimum load capacitance of 12pF. If used in a digital clock, this crystal would result in an error of about 64 seconds per week (24 × 7 × 3,600 × 105.778/106).

To correct this error, we need to set the TM4C RTC trim register to a value greater than 0x7FFF, so that it slightly retards the 1Hz clock every 64 seconds. In the 1,280 second sample interval, 1280/64 = 20 corrections will occur. We need a total of 4,437 counts to be removed from the crystal output every 1,280 seconds, so each correction must be 4437/20 or 221.85 counts per correction. Rounding up gives 222 counts per correction. We can’t quite get to 0ppm, but the result will be a lot better. With a correction, the count will be adjusted by 222 × 20, or 4,440 counts over the 1,280-second measurement period. This will make the clock about 3 counts slow over 1,280 seconds, instead of 4,437 counts fast. Three counts over 1,280 seconds is 0.071ppm, or .043 seconds per week (a bit over 2 seconds per year). Again, it could be that we need something closer to 4,436 or 4,438, but 4,440 is as close as we can get.

The output of the circuit after the trim register is set to 32,989 (0x7FFF + 222) looks like this:

___PPS________RTC__RTC prescaler
0000.0001: 0009-0000.13BB
0000.0002: 0013-0000.13DE
0000.0003: 001D-0000.1400
0000.0004: 0027-0000.1423
0000.0005: 0031-0000.1445
0000.0006: 003B-0000.1468
0000.0007: 0045-0000.13AD <- Trim adjust
-- Snipped lines for brevity --
0000.0081: 0509-0000.13B3

You can see that the first six outputs (60 seconds), the divisor value increases as it did before, about 35 counts every 10 seconds. But by the 70-second mark, it is reduced significantly. In that interval, the first 64-second correction was applied. The ending count isn’t quite the same as the starting count, because the RTC counter continues to run for 5 seconds between the correction at 64 seconds and the output of the next sample at 70 seconds.

By the time 1,280 seconds have elapsed, 20 corrections have been applied, and the divisor count is 0x13B3, which is an error of -8 counts or -0.19ppm or -0.115 seconds per week. I let the circuit continue to run for 5,120 seconds and it resulted in the same -0.19ppm error. Given the 2-count ambiguity in the needed correction, this is very good. Trim corrections of 221 and 223 would be worse, and an error of 0.115 seconds/week is 500 times better than the original 64 second-per-week error. If the error had been the other direction—with the crystal 4,437 counts low over 1,280 seconds—then the trim adjustment of 222 would be subtracted from 0x7FFF, resulting in a trim value of 32,545.

This method allows you to calibrate the TM4C RTC relatively quickly. In a production environment—where you might be calibrating 10 or 100 units at a time—you would have one GPS module driving all the circuits (through appropriate buffers, of course), so they could all be calibrated in about 20 minutes.

In this case, I did all the calibration calculations manually, and then changed the trim value in the source code and recompiled it. In a production environment, you would store the trim value in the TM4C EEPROM, so the code could be the same on all the boards. You could even perform the trim value calculation in the TM4C, itself, with no need for the serial port connection. Once calibrated, the operating firmware would read the trim value from the EEPROM and set the trim register at startup.

It is important to note that the purpose of the trim register isn’t to force the prescaler to be correct on every one-second interval. Rather, it is to periodically adjust the prescale value, so the long-term value of the RTC register—counting 1Hz clocks—is correct. There will be short-term errors, since the 1Hz clock is still wrong 63 out of every 64 seconds.

The calibration so far was all performed at one temperature. But the crystal frequency varies with temperature, so for accuracy over a wide temperature range, you need temperature compensation. The variation in frequency is a parabolic curve, with the nominal (or turnover) temperature at the peak of the curve, and the frequency accuracy (in ppm) changing on either side of that midpoint. Parts per million varies with the square of the temperature difference from nominal. As illustrated in Figure 6, a temperature of 0°C corresponds to an error of 25ppm.

FIGURE 6 – Parabolic temperature vs. PPM error of crystal. The PPM error increases with the square of the temperature variation from the turnover temperature.

The crystal I used was just a generic part and I don’t know the temperature coefficient, but a typical value is about 0.040ppm per degree squared. So, with a nominal (turnover) temperature of 25°C, a temperature drop of 3°C (down to 22°C) would result in a variation of 32 × .040, or 0.36ppm. Not a lot, but if the temperature swing is 10°C, the error would be increased by 2.4 seconds per week. In a car, where temperatures can range from below freezing to over 30°C, the accuracy can therefore vary considerably.

In many applications, you probably don’t need to worry about temperature. If you wanted to build a homemade digital alarm clock, room temperature is fairly constant, so temperature compensation typically is not needed. This is especially true if the 60Hz line frequency is used for timekeeping, and the RTC is just for battery backup. With such clocks available for around $10, you probably wouldn’t build your own, although I think it would make a good senior project for an EE student. As a project, it contains a lot of the system, circuit and firmware trade-offs of a more complicated design, but at a student-manageable level of complexity.

If your application does need temperature compensation, then you need to add a temperature sensor to the circuit. You can then characterize the temperature characteristics of the crystal by using the same method to measure the uncalibrated crystal error, but do it at different temperatures. You then store a table in the TM4C EEPROM of the trim value for each temperature band. However, creating the table requires some kind of oven to hold the temperature of the circuit constant while taking the measurements.

Another way to compensate for temperature is to calculate a new trim value, based on the original trim value, the temperature and the crystal manufacturer’s ppm-to-temperature specification. You still need a temperature sensor, and this is less accurate, because the temperature variation of the crystal frequency has its own tolerance. But it may be close enough, depending on your application, and it eliminates the expense and calibration time of using an oven.

There are also other ways to get temperature compensation. Instead of using an RTC crystal, you can use a temperature-controlled oscillator, such as the ECS XC3158CT, which is a CMOS temperature-compensated oscillator. That, of course, obviates the entire purpose of this article, but it’s an easy solution if it fits your application. The Maxim Integrated DS3234 RTC contains a TCXO, time/date calculation and SPI interface in a single package.

The calibration method I’ve illustrated here is unique to the TI TM4C family of parts, which has the ability to directly read the RTC prescaler value. But the same process could be applied to any MCU that will allow the crystal oscillator to drive an internal or external timer. The Microchip Technology ATmegaxx08 parts can drive a CLKOUT pin from the 32.768kHz oscillator, which can then be used to drive an internal timer/counter, or even an external timer in another MCU.

With the GPS PPS signal on an input pin, the same method used on the TM4C part can be used on these and similar parts. Note that some MCUs support use of a 32.768kHz crystal, but do not have any way to compensate for variations in crystal frequency. There isn’t anything you can do about those, except pick a good crystal or make periodic corrections to the RTC counter itself in firmware.

You can also read the crystal frequency and calculate the trim value from that. You can’t connect directly to the crystal, since that will change the frequency. If you can’t program the crystal output to drive an output pin, you would have to build a buffer for one of the crystal pins and add it to your design. However, design of such a buffer is tricky, because the pins aren’t logic-level voltages, and the impedance has to be high. One drawback to measuring the frequency directly is that the frequency counter has to be more accurate than the accuracy you need from the RTC. Generally, such counters will be expensive.

Sometimes you need an accurate RTC. Calibrating a 32.768kHz crystal in an MCU RTC often requires expensive test equipment and long run times. But using an inexpensive GPS module and taking advantage of the ability to measure the period of the RTC prescaler, you can get good calibration in a short time. 

Crystal Parameters

Crystals have many parameters, but for the purposes of this article, here are the ones that are relevant for 32.768kHz crystals:

Turnover temperature: The temperature at which the crystal is closest to its nominal frequency. Typically, 25°C with ±5°C variation (so it can be 20°C to 30°C, with a nominal value of 25°C).

Operating temperature: Temperature range over which the crystal can safely operate. Typically -10°C to 50°C

Frequency tolerance: Frequency variation at turnover temperature, typically ±20ppm, but ranging from 5ppm to 100ppm depending on manufacturer and crystal part number. You can think of this as being like the tolerance of a resistor, except that it’s measured in parts per million instead of percent.

Parabolic coefficient: The amount the frequency varies with the square of temperature difference from nominal temperature. Typical value is 0.040ppm, ±0.005ppm, per °C2. So, with tolerance included, a temperature change of 10°C might result in a frequency change from 3.5ppm (100 × .035) to 4.5ppm.

Recommended load capacitance: The capacitance from the terminals to ground in a typical MCU circuit. Typically, 12pF to 15pF. Note that in a typical MCU circuit with one capacitor from each terminal to ground, the capacitance at the crystal terminals is the series capacitance of the two capacitors. Two 20pF capacitors have a series capacitance of 10pF.


[1] Stuart Ball, “Something from Nothing: Debugging Embedded Systems with Minimal Resources,” (Circuit Cellar 312, July 2016)




Typical 32.768kHz crystal:

Maxim Integrated |
Texas Instruments |


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Stuart Ball recently retired from a 40+ year career as an electrical engineer and engineering manager.  His most recent position was as a Principal Engineer at Seagate Technologies.

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Calibrating an MCU’s RTC Using GPS

by Stuart Ball time to read: 13 min