Using the I2C protocol

From MCS Wiki AVR
Jump to: navigation, search


I²C bus

I²C bus is an abbreviation for Inter Integrated Circuit bus. It is also known as IIC and I2C.


I²C is a serial and synchronous bus protocol. In standard applications hardware and timing are often the same. The way data is treated on the I²C bus is to be defined by the manufacturer of the I²C master and slave chips.


In a simple I²C system there can only be one master, but multiple slaves. The difference between master and slave is that the master generates the clock pulse. The master also defines when communication should occur. For bus timing it is important that the slowest slave should still be able to follow the master’s clock. In other words the bus is as fast as the slowest slave.


A typical hardware configuration is shown in the figure below:






Note that more slave chips can be connected to the SDA and SCL lines, normally Rp has a value of 1kOHM.

The clock generated by the master is called Serial Clock (SCL) and the data is called Serial Data (SDA).


notice Always check if the pull-up resistors are connected !


In most applications the micro controller is the I²C Master. Slave chips can be Real Time Clocks and Temperature sensors. For example the DS1307 and the DS1624 from .


Of course you can also create your own I2C slaves by programming an ATTINY or ATMEGA . See CONFIG I2CSLAVE

In that case there is AVR Master to AVR Slave communication.





Data can only occur after the master generates a start condition. A start condition is a high-to-low transition of

the SDA line while SCL remains high. After each data transfer a stop condition is generated. A stop condition is a low-to-high transition of the SDA line while SCL remains high.




As said a data transfer can occur after a start condition of the master. The length of data sent over I²C is always 8 bit this includes a read/write direction bit, so you can effectively send 7 bits every time.

The most significant bit MSB is always passed first on the bus.


If the master writes to the bus the R/W bit = 0 and if the master reads the R/W bit = 1.


After the R/W bit the master should generate one clock period for an acknowledgement ACK.


Each receiving chip that is addressed is obliged to generate an acknowledge after the reception of each byte. A chip that acknowledges must pull down the SDA line during the acknowledge clock pulse in such a way that the SDA line is stable LOW during the HIGH period of the acknowledge related clock pulse.


After an acknowledge there can be a stop condition, if the master wishes to leave the bus idle. Or a repeated start condition. A repeated start is the same as a start condition.


When the master reads from a slave it should acknowledge after each byte received. There are two reasons for the master not to acknowledge. The master sends a not acknowledge if data was not received correctly or if the master wishes the stop receiving.


In other words if the master wishes to stop receiving, it sends a not acknowledge after the last received byte.


The master can stop any communication on the bus at any time by sending a stop condition.





Let’s say we have a slave chip with the address “1101000” and that the master wishes to write to that slave, the slave would then be in receiver mode, like this:



You can see here that the master always generates the start condition, then the master sends the address of the slave and a “0” for R/W. After that the master sends a command or word address. The function of that command or word address can be found in the data sheet of the slave addressed.


After that the master can send the data desired and stop the transfer with a stop condition.




Again the start condition and the slave address, only this time the master sends “1” for the R/W bit. The slave can then begin to send after the acknowledge. If the master wishes to stop receiving it should send a not acknowledge.



This example shows you how to setup and read the temperature from a DS1624 temperature sensor.

Connect the DS1624 like this:



Then program this sample into your micro controller and connect your micro controller to the serial port of your PC.



$regfile = "m88def.dat"             'Define the chip you use

$crystal = 8000000                   'Define speed

$baud = 19200                         'Define UART BAUD rate



'Declare RAM for temperature storage

Dim I2ctemp As Byte                 'Storage for the temperature



'Configure pins we want to use for the I²C bus

Config Scl = Portd.1                 'Is serial clock SCL

Config Sda = Portd.3                 'Is serial data SDA




'Declare constants - I2C chip addresses

Const Ds1624wr = &B10010000           'DS1624 Sensor write

Const Ds1624rd = &B10010001           'DS1624 Sensor read


'This section initializes the DS1624

I2cstart                         'Sends start condition

I2cwbyte Ds1624wr                 'Sends the address


'byte with r/w 0


'Access the CONFIG register (&HAC address byte)

I2cwbyte &HAC

'Set continuous conversion  (&H00 command byte)

I2cwbyte &H00                                          

I2cstop                           'Sends stop condition

Waitms 25         'We have to wait some time after a stop



I2cwbyte Ds1624wr

'Start conversion (&HEE command byte)

I2cwbyte &HEE                                          


Waitms 25

'End of initialization


Print                           'Print empty line





'Get the current temperature


I2cwbyte Ds1624wr

I2cwbyte &HAA     'Read temperature (&HAA command byte)


I2cwbyte Ds1624rd 'The chip will give register contents

'Temperature is stored as 12,5 but the ,5 first

I2crbyte I2ctemp                                      

'So you'll have to read twice... first the ,5

I2crbyte I2ctemp , Nack

'And then the 12... we don't store the ,5                            


                                                              'That's why we read twice.


'We give NACK if the last byte is read


'Finally we print

Print "Temperature: " ; Str(i2ctemp) ; " degrees" ; Chr(13);


Waitms 25






You should be able to read the temperature in your terminal emulator.

Note that the used command bytes in this example can be found in DS1624 temperature sensor data sheet.





Config Sda = Portx.x

Configures a port pin for use as serial data SDA.


Config Scl = Portx.x

Configures a port pin for use as serial clock SCL.



Sends the start condition.



Sends the stop condition.



Writes one byte to an I²Cslave.



Reads one byte from an I²Cslave.


Writes a number of bytes to an I²Cslave.



Reads a number of bytes from an I²Cslave.




The design below shows how to implement an I2C-bus. The circuit is using a Mega88 as a master.

The TWI bus is used. While you can use any pin for software mode I2C, when a micro has TWI hardware build in, it is advised to use the TWI hardware.


R1 and R2 are 4K7 pull up resistors.


There are many I2C slave chips available. The example shows the PCF8574. With the additional TWI slave library you can make your own slave chips.

I2 hw.zoom76.png




The following information was submitted by Detlef Queck.


Many people have problems over and over with I2C(TWI) Termination. Use 4,7k or 10 k pull up? How long can the SCL, SDA line be when used with pull ups etc, etc.


You can simplify this confusing problem. Here is a Schematic for an active Termination of I2C and TWI. We have used this Schematic for over 10 years, and have had no problems with it. The I2C (TWI) lines can be up to 80cm (400KHz) without any problem when the Terminator is at the end of the lines.






See also:

Using USI (Universal Serial Interface)Config TWICONFIG TWISLAVE

Languages   English Deutsch  
Personal tools
In other languages