3 Simple Ways to
Share What You Make

With Instructables you can share what you make with the world — and tap into an ever-growing community of creative experts.

PhotosPhotos

Share one or more photos of a project, recipe, or whatever you've made, quickly and easily.

Step by StepStep-By-Step

Share your step-by-step photos with text instructions of what you made so others can do it too!

VideoVideo

Share your how-to video. You'll need your embed code from a video site such as YouTube.

I2C Bus for ATtiny and ATmega

I2C Bus for ATtiny and ATmega
I love the Atmel AVR microcontrollers! Since building the Ghetto Development System described in this Instructable, I've had no end of fun experimenting with the AVR ATtiny2313 and the ATmega168 in particular. I even went so far as to write an Instructable on using switches as inputs, and extended the Ghetto Development System concept to CPLDs.

During a recent project, I needed several switches for setting control values. The AVRs did not have enough I/O pins, so I had to think of something. I could have tried a complex input system with a keyboard and display, but the ATtiny2313 would have run out of resources. Fortunately, Atmel has provided a way around this problem by including an interface that can link to additional chips (such as memory or I/O ports) with a simple two wire interface. That's right, by using just two I/O pins on an AVR we can access many additional I/O pins, and other resources as well.

This two wire interface is formally known as the Inter-Integrated Circuit bus, or just the I2C bus and was invented by NXP when it was still Philips Semiconductors. If you're reading this Instructable then you've probably heard of the I2C bus and may even have used it on a PIC or other microcontroller. While conceptually very simple, and supported by hardware resources on the AVRs, software drivers are still necessary to use the I2C bus. Atmel provides Application Notes (see the Resources later in this Instructable), but these are incomplete and don't show any examples beyond communicating with another AVR device.

It is not the purpose of this Instructable to teach anyone how to create I2C drivers for the AVRs. Rather, I'll provide expanded versions of the Atmel drivers for ATtiny2313 and ATmega168 devices, I'll explain the requirements and restrictions that apply when using these, and I'll show you working examples of I2C devices. After you work through this Instructable you'll be able to use the I2C bus successfully in your AVR projects. Obviously, you can ignore the drivers for either tiny or MEGA if you're only interested in one of them. For those interested in learning more about the I2C bus, I'll provide links to appropriate material.
 
Remove these adsRemove these ads by Signing Up
 

Step 1What's All this I2C stuff anyway?

What\
The I2C bus is a simple, two-wire connection that can link multiple devices together and allow them to exchange data. In its simplest form there is one master device that communicates to multiple slave devices. All devices are connected in parallel to the two wires of the I2C bus. The two wires are known as SCL and SDA. SCL is the clock line and is controlled by the master device. SDA is the bi-directional data line. To transfer data, the master sends out a slave address combined with a one bit read/write flag. If a write is desired, the master will continue to send data to the addressed slave. If a read is requested, the slave will respond with data. To coordinate transactions, the SCL and SDA lines are manipulated by the master and the slave to signal several conditions. These include START, STOP, ACK (acknowledge) and NAK (no acknowledge). The details of these conditions are handled by the drivers. The true geeks among you can learn all the details in the links provided at the end of this Instructable.

The electrical requirements are pretty simple. The master and the slaves must use the same level for Vcc, the grounds must be connected, and the SCL and SDA lines must be pulled up to Vcc. The value of the pull-up resistors is precisely determined by a calculation based on the total capacitance on the bus, but practically can be pretty much any value between 1.8K and 10K. I start with 5.1K and use lower values until it works. This usually isn't an issue unless you have a lot of devices or long lengths of wire between devices.

The nominal data rate on the I2C bus is 100Kbits/second. Rates of 400Kbits/second, 1Mbits/second, and beyond are possible as well, but aren't supported by the drivers in this Instructable. All I2C devices will work at 100Kbits/second.

The ATtiny2313 and the ATmega168 each implement the I2C bus differently. ATtiny2313 uses the Universal Serial Interface (USI) hardware - which can also be used for the SPI bus. ATmega168 has dedicated hardware for the I2C bus known as the Two Wire Interface (TWI). Once the drivers are written, these differences are mostly transparent to the user. One significant difference is in the software: The ATmega168 I2C driver is interrupt driven while that for the ATtiny2313 is not. This means that an ATmega168 program does not have to wait for I2C data transfers to take place, but only needs to wait before initiating another transfer, or until data arrives from a read operation. The examples and discussion to follow should make this clear.

I2C addresses are 7 bits long, so up to 127 devices can be on the bus if each has a unique address. As shown in the figure, this 7 bit address is shifted left one bit and the least significant bit is used to flag a read or write of the device at the address. Thus the complete slave address is an 8 bit byte. The actual address is partially determined internally to the device and can't be changed (4 most significant bits), and partially determined by bits that may be connected to device pins (3 least significant bits) that can be tied high or low to set a specific address.

Sounds confusing, but an example will make this clear. The PCA8574A data sheet shows that the four most significant bits of the I2C address will always be 0111. The next three bits are determined by the settings on pins AD0, AD1 and AD2. These pins can be tied to ground or to the positive voltage supply (5 volts) to represent 0 or 1 respectively. So the range of possible addresses is 38 to 3F hexadecimal, as shown in the other figure from the PCA8574 data sheet. So by changing the address bit settings, up to 8 PCA8574As can be on the I2C bus at the same time. Each will respond to its specific slave address only. If even more I/O ports are needed, the PCA8574 can be used. The only difference between the PCA8574 and the PCA8574A is that the I2C slave address range of the PCA8574 is 20 to 27 hexadecimal.

Determining the address of a given device can be confusing since some data sheets consider the read/write bit to be part of the address. Read the data sheet carefully and keep in mind that the slave address will be 7 bits long. The read/write bit should be treated separately. Again, an example will help. The data sheet for the 24C16 EEPROM we'll experiment with says the first (most significant) four bits of the slave address are 1010. The next three bits can be determined by A0, A1 and A2; but note the data sheet also covers 24C01 through 24C08 which are smaller sized EEPROMs. The figure from the data sheet shows that the settings of these address bits are ignored as the size increases and are completely ignored for the 24C16. That is, the last three bits don't matter and the 24C16 really uses all I2C slave addresses 50 through 57 hexadecimal. The range of slave addresses will actually address different sections within the 24C16. The first 256 bytes are at address 50h, the next 256 at 51h, and so on up to the last 256 at 57h - for a total of 2K bytes. Since the address of the PCF8570 RAM we also experiment with is in this range, the 24C16 and the PCF8570 can't be used together.
« Previous StepDownload PDFView All StepsNext Step »
34 comments
Mar 8, 2012. 10:58 PMMrShmoe says:
One more (dumb) question:

How do I get my AVR Studio 4 to build your code? In other words, how do I get AVR Studio to process your makefile?

Newbie here, I know.
Mar 6, 2012. 11:09 PMMrShmoe says:
Curious: I am trying to use I2C to communicate between two ATtiny44's. Question for you: how do I know what address each has? This is missing from the data sheet.

Also, is there a way using I2C to be both a master and slave? I'm thinking of having one be the master, and the slave toggling a GPIO when it wants to communicate...initiating a read, for example.

Any code that would help me with that? I am relatively new to this. :-(
Mar 8, 2012. 9:01 PMMrShmoe says:
Thanks! Question though: Where do I define the I2C address? Sorry, newbie here. Maybe this is a #define already in your code?

Others have mentioned that there is a TWAR register...but I searched the ATtiny44 datasheet for such a register and none exists.

Thanks again for the great advice!
Jan 10, 2012. 12:32 PMadumas says:
Hi... I'm interested in using an ATTiny85... will it work? If not, what changes do I have to make
Apr 5, 2011. 6:14 AMhvneck says:
Great tutorial!,

I'm making a turntable for modeltrains which uses a lot of I/O and only has 2 wires available (along with supply of course) to control all functions on the rotating part of the bridge.
Because of the fact that the controller (ATMEGA8) does have to do all the controll-functions (motor / locks / position sensors etc.) as well as the reception and feedback of the loconet signals (protocol for controlling aceccories on a model rail layout) I'm bound to run the ATMEGA8 at the full 16MHz. Will that be possible with your TWI library? When yes, what do i have to modify? Or are there other options. Thanks in advance!
Oct 23, 2010. 9:08 PMmathman47 says:
You might want to change your eeprom link, just to be complete. The company was sold. Unfortunately, there are 679 devices listed & I haven't a clue as to which one(s) are applicable. Here is the page:
http://www.onsemi.com/PowerSolutions/parametrics.do?id=2311&lctn=home

This is a print, study, & keep Instructable. Thanks for all the information.
Oct 10, 2010. 10:16 PMqli029 says:
GOOD ONE
CHEERS
Sep 30, 2010. 1:13 PMRalphxyz says:
Where are the downloads?? I get a page not found!!

Great article.

Ralph
Sep 30, 2010. 2:06 PMRalphxyz says:
Got the download from the web download link, the link in the .pdf is broke!!

Ralph
May 4, 2010. 12:15 AMgremlin_1 says:
I really appreciate the author spending the time to write this tutorial.  I have built the ATTINY2313 and PCA8574 I/O expander circuit. However, I have one question on the schematic.  The LEDs on the PCA 8574 seems to be backward. They will never turn on. Maybe the common  VCC connection is wrong and it should be GND instead? Can the author clarify it?  Thanks.
Apr 13, 2010. 1:38 PMtissit says:
Atmel claims it's possible to use AVR port pull-ups for the I2C bus pull-ups. I haven't figured out a way to make that approach work.

Have you tried setting the pin and then twiddling the DDR instead of the actual pin. ISTR that being the usual way to do open collector-ish lines.
Apr 13, 2010. 1:20 PMtissit says:
Not all avr's have TWI, though. It would be nice to see some great writeup on developing a bitbang driver. That'd be useful for other controllers as well.
Feb 9, 2010. 6:29 PMnolte919 says:
I used this great instructable and referenced it a couple times in my instructable I2C Controlled 7 Segment LED Display.  I used the LED display as part of a digital thermometer.  I really like I2C.  I also used external 4.7k pullup resistors on each I2C line rather than relying on the AVR internal ones.
Feb 10, 2010. 8:57 PMnolte919 says:
Too cool.  The project I'm working on right now will have an AVR as an I2C slave to put a 16x2 LCD character display on an I2C bus.  To try and make an LCD module that's super easy to add to a project.  I'm going off the slave versions of the Atmel app. notes you used for this project.
Feb 11, 2010. 9:08 PMnolte919 says:
Yeah, the one I plan on making is considerably cheaper than any I could find and I plan on making the user interface easier too.  And as I'm sure you understand, I'm as much interested in learning and teaching how to make a slave I2C device as I am in making a better I2C LCD display.  I think the I2C protocol is so versatile and  over 100 devices with only 2 pins is hard to beat.
Dec 23, 2009. 12:42 PMdtr2 says:
 Do you have a "twi slave" code for for ATTINY2313? I want to control multiple of those from a master ARDUINO...

Nov 24, 2009. 1:06 PMroagile-2007 says:
Hey my friends i need make the arduino send a a message to the nxt please how do i make it.I want to program the nxt to use nxc connceted to the arduino,the arduino will be connected to the rfid reader.the rfid tag will be read and the arduino compares with the tags olready stored in its memory,if it corresponds it sends the msg to the nxt,plz help is vry vry agent
Oct 21, 2009. 9:12 AMLYNTRAN says:
Dear Developer of this source code,

I have a question about the source code.

I went over the code written for ATtiny2313. You select External, positive edge for the Shift register and Software clock strobe (USITC) for 4-bit Counter (USICS1=1, USICS0=0, USICLK=1). In the function unsigned char USI_TWI_Start_Transceiver_With_Data() you define the constant below.

  unsigned char const tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
                                 (0x0<<USICNT0);                                     // set USI to shift 8 bits i.e. count 16 clock edges.

Why the program has to count 16 clock edges for 8-bit transfer? I thought the programhas to count 16 clock edges for 8-bit transfer when USICS1=1, USICS0=0, USICLK=0 or when USICS1=1, USICS0=1, USICLK=0.

Please explain.

Thank you so much,
Jul 12, 2009. 6:23 AMfabelizer says:
Great experiment, if I can only get it to compile in AVR Studio4! Does anyone have any tips on opening this project in AVR Studio 4? Even though Studio4 allows me to manually open the USI_I2C_Port.c file, when made into a project file, it complains: >Coordinator: None of the available object file readers can read the specified >object file. Please check the format of the object file. >Error loading object file I:\My Documents\AVR\Programs\I2C\USI I2C\I_O >Port\USI_I2C_Port.c and stops. Suggestions? Thanks, -fab
Jul 12, 2009. 11:32 AMfabelizer says:
Ok, I got it compiled. Apparently the USI_TWI_Master.c has to be put into the source files area in the project, then there were a few minor version related changes, but the code is now in the tn2313! -fab
Feb 2, 2009. 8:42 PMp2otoole says:
I tried using the program TWI_I2C_EEPROM.c, with the circuit hooked up according to the schematic, of course, and got (1) waring: return type of 'main' is not 'int'. (2) error: 'CLKPR' undeclared (first use in this function)
Other than that, this program was what I have been looking for, and I know its gonna work for me,
Thank you
Feb 3, 2009. 11:44 AMp2otoole says:
I was trying to upload to an atmega8, which has the same pin layout and number of pins as an at-168. Also the EEPROM ckt that I have is a 24LC512; two strikes against me right there, I reckon. But I do have an atmega168 that I could use. I don't have the other ckts. that you discussed in this tutorial (port extender, etc) I would really like to get this program going, as it is one that I have been searching for; it will fit right into my plan. Thank you
Jan 4, 2009. 10:36 AMBrianCatlin says:
Impressive. Well written!

Pro

Get More Out of Instructables

Already have an Account?

close

All Steps Viewing
View all steps of an Instructable on the same page when you're a Pro Member.

Upgrade to Pro today!
41
Followers
8
Author:doctek