Monday, March 7, 2011

Testing the I2C/TWI controller with a ds1307...

The DS1307 (Maxim-ic)is a very common real time clock that communicates over I2C (which makes it the perfect choice for testing the module we just built).  The typical way to handle the 1307 is to write a byte to it to set the internal pointer and then read back multiple bytes of data.  Many of the variants contain additional memory that you can use to store your own data, but in general the first 7 or so bytes contain data about the current time.  This particular breakout came from Adafruit (one of the good online retailers), but the chips themselves are available.  The two resistors next to the ic are the pullups to Vcc, there is also a filter cap, a 32.768kHz crystal and a battery to allow the ic to continue to run where power is otherwise unavailable.

This is a borduino (and arduino variant designed for using on breadboards)... Inexpensive, very easy to program and with a very vibrant online community it's one of those things that's good to have hanging around.  I used this one to confirm the ds1307 was working correctly and to get waveforms and logic analyzer traces that I know are correct to compare to the design I am working on...

When working on hardware designs it's a good thing to have a cpld or fpga available.  I like to use the vendor boards (in this case a spartan3AN by Xilinx).  These boards usually have way too many devices that you will never use, but are also usually built very well and have plenty of io to work with...

The problem now is that the voltage the DS1307 needs is much higher than the FPGA can handle.  This level converter is one of my favorite little chips to have around... The P82B96P by Texas Instruments is really intended to split the I2C lines to separate Tx/Rx pairs for longer distance communication than the I2C is typically capable of handling.  This little chip handles the 5 volt signals from the ds1307 on the bus and the other side can handle a much wider voltage range, and by tying the Tx/Rx pins together we can connect it directly to the fpga.  There are many level converters from other companies that work as well, but this is the only one that just always work for me.

I know everyone is supposed to have neat perfectly aligned wires, chips in neat little rows, everything perfectly planned and it's supposed to work perfectly the first time the power is turned on... well, not for me... It's very rare that I get everything right the first time, and things usually end up as a confusing mess before I figure out what was wrong.  A few things I like to do are: 1) always try to have a known working set of devices that are using the protocol (or as close to the protocol as possible) that you are going to use in your design 2) have lots of jumper cables in different colors available 3) use multiple breadboards for components (especially if you are working with different voltages, and have pullup resistors permanently in some places) 4) stick a logic analyzer (I like the open bench logic sniffer) in a breadboard because it's an awful lot easier to use than little clips.

This is a quick example of how the twi/i2c module we built previously should work.  Here we are going to address the slave for writing and then send a byte (00000000) to set the internal pointer of the ds1307 after which we will address the slave for reading and pull 7 bytes from the slave containing the time data. The start and stop signals and the acks are all handled automatically, but we send a nack after the last read from the slave so the slave releases the bus an allows the master to send a stop signal.  I added a separate instance of the bit detector as well setup so that the start/stop/data0 and data1 signals are updated when any of them change (the actual signals last for 1 clock only but the system clock is much faster than the analyser is running so they don't show up well - only updating them all when a new signal is detected works very well to get around "invisible signals").