I2C Real-Time Clock

As I mentioned in previous posts I volunteer at the local non-profit recycling center.  Some of the electronics stuff that gets dropped off kind of makes me feel like a technology archeologist and I have a fantasy that the History Channel will show up some day wanting to do a TV series about us.  Not likely, but it doesn’t hurt to dream.  One of the “vintage” items I ran across a couple of months ago was a controller board that had some sort of black epoxy module.  On closer inspection I discovered that it was a DS12887 Real-Time Clock (RTC).  This module was popular back in the early days of desktop PCs and provided not only the battery backed clock function, but also the battery backed CMOS memory.  The most interesting thing, though, is that the backup battery is encapsulated inside the module itself.  The bad part is that there is no easy way to bypass the internal battery if it runs down.  To do so requires some careful scraping away of epoxy in the vicinity of where the battery connects to the module electronics, snipping one pin to disconnect the old battery, and then some awkward soldering of a battery holder for the new battery.  Why would anyone do that?  Well, just to prove that it can be done.  I went ahead and did the scraping and discovered that the internal battery still had almost 2.9 volts which is enough to still do its job after almost 20 years.  That got me to thinking about more modern RTC chips so I decided to buy one of those cheap little modules on eBay that includes an I2C RTC and a separate I2C serial EEPROM.  In this post we will see how to integrate that module with the I2C LCD module from a previous post.

RTC I2C Module

I2C RTC Module

The I2C module I have is similar to the one shown here.  The pins are self-explanatory but there are a couple of other things to point out on this module.  The board comes with a default I2C address of 68 hex for the RTC and 57 hex for the serial EEPROM.  There are three sets of solder pads on the board labeled A0, A1, and A2.  Those can be used to change the address of the EEPROM by shorting across one or more of the pad sets.

In the picture of the board you can see a red rectangle that outlines a surface mounted resistor.  The reason that is pointed out is that the module is designed with a simple trickle charge circuit for the battery which is supposed to be a 3.3 volt Lithium-ion type.  The board I received had a non-rechargeable Lithium battery (CR2032) instead.  In that case, the battery either needs to be replaced with the rechargeable type or the resistor on the board needs to be removed.  The easy way to remove it is to snip the resistor in half with some wire cutters and then unsolder each half from the board.

I have included copies of PDF documents here that have the specs for the RTC and the EEPROM and a schematic of the module.

RTC Documents


LCD RTC I2C Interface

The schematic shown here is built on the circuit that was used for the I2C LCD interface.  The new RTC module is just wired in parallel to the SCL and SDA lines that go to the LCD module.  In addition, there are two momentary contact push button switches that are used for setting the time and for reading saved memory locations.  Each switch does double duty with switch 1 getting us into the time setting mode and switch 2 getting us into the memory read mode.  While in one mode or the other, the opposite switch is used to toggle through choices.  That minimizes the number of I/O pins that are needed.


The software link is listed below.  While it is targeted for the 12F683, it is easily ported to bigger versions of the PIC.  Mostly it requires changing names like TRISIO to TRISA, and GPIO to PORTA.  You will also need to change the line that identifies the PIC version (LIST=) and the INCLUDE file but those are intuitive changes.  The __CONFIG line may also need tweaking just because one or two of the labels used are spelled differently in some of the INCLUDE files.  As we’ve seen before, the 16F688 (14-pin PIC) could be used with the same physical pin connections as the 12F683 if you want more I/O pins.

The software starts with the I2C code written for the LCD interface in Episode 22.  In that example all we worried about was writing to the I2C serial bus.  With the addition of the RTC and EEPROM we now have to include capabilities for reading from the I2C serial bus.  An I2C read operation starts with writing the I2C device address (we now have three devices on the bus).  That is followed by writing the memory or register location for either the RTC or the EEPROM.  At that point, the PIC switches the SDA line to be an input and uses the SCL line to clock data bits out of the RTC or EEPROM.  At the end of each byte received, the PIC sends an acknowledge to the slave device.

In addition to the new I2C read routines, there are a lot of routines to interface to the RTC and the EEPROM.  RTC capabilities include writing of initialization data, reading of the time registers, and reading of the temperature registers.  The temperature seems like a bonus capability but it lacks in accuracy compared to dedicated temperature sensors.  Even though we have access to both the integer and fractional portions of the temperature we still only get accuracy to +/- 3 degrees.  In addition, the temperature is not of the surrounding air.  It is the internal temperature of the chip that is used to compensate the clock oscillator.  The RTC does include a few registers other than the time and date information used here.  They include a couple of alarms and also a register to control the frequency of the square wave output (SQW) on the module.  There is also a control register that allows you to change from 24-hour time mode to 12-hour.

The routines for the EEPROM basically just control read and write operations.  The memory size is 32k bytes and is organized as 128 pages, with each page containing 256 bytes.  That means that the address sent to the EEPROM is two bytes, with the first byte being the page and the second byte being the location within the page.  In the example code the integer value of the temperature is written to the EEPROM once a minute.  The temperature includes a sign bit so each storage uses two memory locations because, at that point, the temperature and sign have been converted into ASCII characters.  That makes for a maximum of 16384 data points but, for simplicity sake, that number is limited to 9999.  The way the software is currently written the write address will reset at each power-on of the PIC.  That could be changed so that the last known write address is also saved to the EEPROM and then read back at power-on.

As mentioned in the hardware section, each of the two switches does double duty.  When switch 1 is depressed the software enters time initialization mode.  Once in the initialization mode, switch 2 increments through the values for each portion of the time and date.  For instance, you can toggle through 0-23 for the hours.  After the desired value is set for an option, pressing switch 1 will advance to the next time/date option.  When all options have been completed (day of the week is the last option) another press of switch 1 will cause an exit from the initialization mode.

During normal time/date display, a press of switch 2 will cause the software to enter the EEPROM read mode.  The display will show a counter on line 1 that indicates which entry is being read (1-9999) and how many total entries have been stored since power on.  Line 2 of the display will show the temperature value for that storage location.  Each press of switch 1 will advance to the next value stored in the EEPROM.  If all stored values have been read, then the LCD will display “DONE”.  A press of switch 2 will cause an exit from the EEPROM read mode at any point during the process.  That’s it for this post.  Check out my other electronics projects.