I2C Tutorial

advertisement
I2C and the Analog-to-Digital Converter
What you need to know for the Self-test project
Start by recalling the brief introduction given in the project lecture slides. There was a diagram of the
entire computer and I/O architecture:
In this diagram, there is an I2C Controller block. You can think of it as a link between the 16-bit I/O bus
of the Simple Computer (used to “talk” to a variety of I/O devices, as we know), and ANOTHER I/O bus,
the I2C bus.
The I2C bus is a serial bus: essentially a 1-bit data bus instead of the 16-bit I/O bus. The I2C Controller
does all the hard work of accepting commands from SCOMP on the 16-bit I/O bus and handling the
sequence of operations needed to send or receive data from any of several possible devices. This is
shown in the picture below.
SCOMP
DATA[0..15]
Audio Codec (used
for tone generation)
I2C Controller
Enable signals, Clocking, Reset,
IO_CYCLE, IO_WRITE
Serial Clock,
Serial Data
TV Decoder (not
used, currently)
Note the “normal” IO bus that you have seen in Lab 8 on the left side of the figure above. The I2C
Controller is just another IO device, addressed at a specific I/O location, just as the switches are at
address 0x00, the LEDs are at address 0x01, and so on. But when the I2C Controller is given a command,
it is a request that includes a target address ON THE I2C BUS, as well as a desired function to perform. In
the example above, it might be a request to send a command like “volume adjust” to the Audio Codec
chip, which has a different address than the TV Decoder chip. The same SCOMP I/O address (i.e. the I/O
address of the I2C controller) would be used to address the TV Decoder, but a different address/function
command would be sent.
Now, let’s clarify an oversimplification in the very first figure (the one on the previous page). It shows a
single I2C Controller in the SCOMP architecture. Actually, you were given TWO I2C Controllers in the files
that you used in the first week of the project. An accurate depiction is shown below.
Enable signals, Clocking, Reset,
IO_CYCLE, IO_WRITE
SCOMP
DATA[0..15]
I2C Controller
Reset, Clocking
ONESHOT_I2C
(A simple I2C
controller)
Serial Clock,
Serial Data
A/D Converter
I2C bus between
DE2 and Robot
Audio Codec (used
for tone generation)
Serial Clock,
Serial Data
I2C bus on DE2
TV Decoder (not
used, currently)
There are actually two I2C busses. One is entirely on the DE2 board, and the other one goes through the
DE2 daughterboard down to the inside of the robot, where the A/D converter is located. The I2C
Controller for the Robot I2C bus is addressable by SCOMP. The I2C controller for the DE2 I2C bus, called
ONESHOT_I2C, simply does an automatic configuration of the Audio Codec so that you can later use it to
generate tones. (Specifically, it enables the analog audio output, sets the volume, and does a few other
things that you would almost certainly not want to do any differently yourself.)
So, you cannot “talk” to the ONESHOT_I2C from SCOMP, and that is just less work for you, anyway. But
you CAN talk to the other I2C Controller, and will need to do so to read the robot battery voltage. The
I2C Controller, appropriately called I2C_CONTROLLER, has three internal registers at three different
addresses in the SCOMP I/O space. You can figure out those addresses (or change them, for that
matter), by looking at the IO_DECODER device that was part of the Week 1 exercises. But, here’s the
answer. The important addresses are:
I2C_CMD (used to tell the I2C Controller what to do): address 0x90
I2C_DATA (the data to send the target device or receive from the target device): address 0x91
I2C_BUSY (an indication that the activity on the I2C bus is in progress): address 0x92
I2C allows devices to send and receive bytes of data, but every single different device in the world with
an I2C interface has its own way of interpreting that data. This is deliberately a generic controller that
you have been given. What is always true is that you first send a word to I2C_CMD that describes what
device you want to talk to, whether you are reading from it or writing to it (or both), and how many
bytes you are sending or receiving. The specifics are given in the comments of the code provided:
-----
I2C_CONTROLLER.vhd
An SCOMP peripheral to interface with I2C devices.
Capable of sending up to two bytes and reading up to two bytes at a time.
Created by Kevin Johnson. Last modified 2013-03-07
-- SCOMP interface:
-- Three IO addresses are used: I2C_CMD, I2C_DATA, and I2C_BUSY.
--I2C_CMD contains the bits [00WW 00RR AAAAAAAA] where:
-WW is the number of bytes to write (0, 1, or 2)
-RR is the number of bytes to read (0, 1, or 2)
-AAAAAAAA is the 8-bit I2C address of the device
--I2C_DATA is a read/write register. Write to it the data you wish to send,
-and read from it any data received. Writing to this register starts the
-I2C transaction, so:
-I2C_CMD must be set BEFORE writing to I2C_DATA.
-Even if no data is to be sent, something must still be written to I2C_DATA
--I2C_BUSY is a read-only register that allows for polling the progess
-of the I2C transaction. A non-zero value indicates that this device
-is busy and will not accept additional commands or data.
-Zero indicates that this device is ready to accept commands or data.
-- Example of typical usage:
-- Write 0x2134 to I2C_CMD
; command to write two bytes then read one byte, I2C
address 0x34
-- Write 0xAA55 to I2C_DATA
; send the bytes 0xAA and 0x55 over I2C, then read one
byte from I2C
-- Read I2C_BUSY until it returns 0
-- Read I2C_DATA to retrieve the byte that was read from the I2C device.
Since there is only a single I2C device (the analog-to-digital converter, or ADC) actually connected to this
controller, all that remains is for you to understand what it expects in terms of an address and data. It is
actually a simple device. Its datasheet will be posted on the project page, but you may find it confusing.
The summary of how to access the ADC is as follows:






The address of the ADC on the I2C bus is 0x90, and you use this address both to write to it and to
read from it.
When it first powers up, you need to write a specific byte to it once to set it up. The datasheet
refers to this as the “Control Byte,” and for this application it must be 0x00. (Specifically, this
disables the unused analog output, configures the analog inputs as “single-ended,” and selects
analog input channel 0, which is the one connected to the battery.)
Once it has been configured, you only need to read a single byte from it whenever you want the
ADC value, but note the comments in I2C_CONTROLLER.VHD that say that you always write to
I2C_DATA to begin ANY operation (including reads).
The first value returned by the ADC (after power-up and configuration) is always 0x80, and is not
valid data (other than possibly as a test that you are correctly accessing the ADC).
All subsequent values (numbers between 0 and 255) are proportional to a voltage on a scale of 0
to 5 V where 256=5V. For example, a value of 128 is: 128/256*5V, or 2.5V.
The actual battery voltage is larger than this by a factor of (118+487)/118. See the lecture slide
called “How do I test the battery” for an explanation.
It is a complete coincidence (and perhaps unfortunately confusing) that one of the three SCOMP I/O
addresses of the I2C controller is 0x90 and the address of the ADC on the I2C bus is also 0x90. Don’t lose
sight of the fact that the SCOMP I/O address is something decoded in IO_DECODER to produce a “chip
select” for I2C_CONTROLLER, while the ADC decodes its address internally when it sees a message on
the serial I2C bus. You could change the address of the I2C_CONTROLLER device, but the address if the
ADC chip itself is built into the chip.
Download