Next up, you need to let the connected modules
know which one you’re going to communicate with, in the
same way as you’d call a person out of a group by name.
Each I2C module has a unique address (or address range)
that is assigned by NXP — seven bits in total. Some
modules allow you to set the last few address bits by
connecting them to 5V (resulting in a 1 bit) or to GND
(resulting in a 0 bit). We’ll see this in operation in our
project later. The address byte is made up of the seven-bit
module address, along with an eighth R/W bit that
specifies whether you want to write to (a 0) or read from
(a 1) the module.
For each byte sent, the receiver of the byte needs to
acknowledge that it has been received with a ninth bit.
This is called an “ACK” and is a 0 over the SDA line. If the
receiver doesn’t acknowledge (called “NACK”), then the
transmission is deemed not to have been received. You’d
need to decide in your software how to handle this. For
example, you may want to retry or terminate the
communication for a period.
After the address has been acknowledged, you’re
ready to start communication. Remember that the
direction of the communication depends on the value of
the last bit in the address byte.
If you want to change the direction of the data, you
can simply re-issue another start condition (called a
repeated start) and resend the address byte with a
different data direction bit value.
Finally, to end a transmission, a stop “condition”
needs to be sent. This is the opposite of a start condition,
in that the SCL is first released high (the clock is stopped),
and then the SDA is released back to a high state.
Using the Protocol
Understanding how the protocol works is not that
straightforward. Thankfully, the microcontroller takes care
of much of the low-level detail by means of its two wire
serial interface — you don’t need to know which lines to
hold high or low at what stage. The Atmel datasheet
actually does a pretty good (and in-depth) job of working
through the TWI module if you’re interested in the
technicalities. Okay, so we’ve had a quick look at how
modules communicate, but not yet what they
communicate. That is a whole other challenge!
I2C modules (and SPI modules for that matter) are
usually able to perform more than one type of function
and often allow you to configure their behavior in certain
ways. For example, an EEPROM module may only allow
you to write to a specific address or to read from a
specific address. A real time clock, on the other hand,
could allow you to set the time, read the time, configure
alarms, specify the format that the time is in, and more.
Each module behaves very differently, and therefore needs
to be communicated with differently. Brace yourself,
because we need ...
... More Datasheets, More Registers
Each module you’ll be using over I2C will behave
differently. It would be impossible to standardize an
interface because the range of functionality varies so
widely. As you could guess from our interactions with the
ATmega328P, this means a datasheet to detail the
interface and using registers to access the functionality. It
would be impossible for an article — or dare I say it, even
a book — to cover all the I2C modules out there; so let’s
work through a project that interfaces with an I2C module
or two to get a better understanding of the protocol. I’m a
big believer that the most effective learning happens by
54 September 2015
Rock Around the RT Clock
Real Time Clocks are wonderful additions to projects.
Sure, they do what they say (act like a clock), but as most
microcontrollers have no sense of human time or timescales,
a clock can be far more useful than simply telling the time.
Here are some features that you could expect from RTCs:
• Set and Tell the Time: Yes, it goes without saying! You’ll
need to get used to the specific registers that are needed to
set and read the different elements of time — including
configurations like time format ( 24 or 12 hour) and day of
week. A good RTC is also able to handle leap years for you.
• Alarms: These are great, as they allow you to schedule
specific actions to take place at specific times without you
having to write the code to keep checking “is it time yet?”
Alarms can often be set to go on a specific
year/month/day/hour/minute/second — so you can get really
specific about when events take place. Perhaps you only
want that project to come to life at midnight on Halloween.
You would normally use an alarm to trigger an interrupt on a
specific pin on your microcontroller, and have the
microcontroller take it from there.
• Backup Battery: The clock on my home oven drives me
crazy — each time the power cuts (a common occurrence
where I live), I need to set the time again. Fortunately, your
project can have a backup battery (a tiny coin cell) so that
you don’t face the same frustrations. Some RTCs will even tell
you when the power cut, so you can compensate for events
that should have occurred during the outage.
All of the above are controlled through registers on your
RTC — registers that you access through the I2C interface,
and registers that are detailed in the datasheets.