from EEPROM. We kick the read off in a similar way: Start
condition, address with write bit set, send memory
location. Wait — did that seem counter-intuitive? We set
the write bit, but we want to read data!? The write and
read bit don’t refer to the operation we’re performing at a
module level (i.e., writing to memory or reading from
memory), it refers to the operation being performed
between the module and MCU. In this case, we need to
write to the module in order to tell it which address we
want to read from. Carry on reading through the code and
it should make sense.
So we send the memory location (high and low bytes),
and then we issue another start condition (called a repeated
start). This tells the module we’re going to do something
different in the same conversation. Then, we re-address the
module with the read bit set. This tells the module to get
ready to send us the data we requested in our initial write.
We read this data and once we’ve got what we want, we
terminate the conversation with a Stop condition.
EEPROM is Mastered
You’ve now mastered the EEPROM — and got to grips
with understanding how to use read and write. Remember
that with most modules, you’ll need to write to a device to
tell it what you want to read. All the EEPROM-related code
in the project is stored in the files “EEPROM.c” and
“EEPROM.h” at the article link.
Your Turn — The RTC
Now that you’ve got a feel for how I2C works, I’m
going to give you a turn to interpret the code for the RTC
— you’ll find it in “RTC_MCP79400.c” and “RTC_MCP
79400.h” also at the article link. Before I do that, though,
there are a couple of principles I want to run through.
Registers
The RTC uses registers — and lots of them! There are
registers to set seconds, registers to set and read minutes,
hours, days, weeks, months, years, leap years, days of the
week ... and then alarm registers, configuration registers ...
you get the picture. The only way to master this module is
to read the datasheet ... a number of times!
Register Names: As this is an external module, Atmel
Studio doesn’t know the register names. This means you’ll
need to define these yourself if you want to make your
code readable. Take a look at
the file “RTC_MCP79400.h” —
it contains the address names
and bit numbers for the most
common registers ... and yes, I
had to type them all in
manually off the datasheet!
Register Values: To set a
value in a register takes a
couple of writes — one to
specify the register you want to write to, and another to
specify the value that goes into the register. To read from
a register, you’ll follow the same process as you did when
reading from the EEPROM — except that the register
address is only one byte, so it doesn’t need to be split into
high and low.
Changing Register Values: This is an important point.
You can’t change single bits in the RTC’s registers like you
would in your microcontroller’s registers — if you write a
single bit over I2C to a register, you clear all other bits in
the register and only set that one bit. Not ideal! If you
want to preserve the other bit values in a register, you’ll
need to read the register value, perform your bitwise logic
on the value you’ve read, and then write the entire register
back again.
Binary-Coded Decimal
Binary is binary, right? Why is the datasheet littered
with references to “Binary-Coded Decimal?” Binary-Coded
Decimal (BCD) is not as common as it was historically, but
nevertheless is fairly common in RTCs. It is a way of using
binary to represent individual digits in a number — usually
four bits to represent a single digit (0-9). Figure 8 shows a
representation of the RTCMIN register (which stores the
“minutes” portion of the time), and a few BCD examples.
To make things simpler (well, only slightly), there are a
couple of helper functions in “RTC_MCP79400.c” that
convert between BCD and decimal. Unfortunately, BCD is
a reality, and I grumblingly learned to live with it. If BCD
sounds like something that interests you, there is a pretty
comprehensive article on Wikipedia that you can sink
your teeth into.
Configuration Registers
There are a couple of important configuration
registers that you need to know about, apart from the
main timekeeping and alarm registers:
RTCSEC: Bit 7 of RTCSEC is “ST” — this bit starts the
oscillator. Without an oscillator, your clock isn’t ticking, so
ensure that you set it on startup.
RTCWKDAY: This has a number of useful bits:
• OSCRUN tells you whether the oscillator is running
(useful for fault checking and troubleshooting).
• VBATEN needs to be set to 1 if you’re using a
backup battery. Without this, the RTC doesn’t know to
60 September 2015
Figure 8: Binary Coded Decimal — an example.