I2C Communication in AVR Microcontroller : PART 2

I2C Bus Protocol : The IIC  ( Inter-Integrated Circuit ) is a bus interface connected which used in many devices such as sensors, RTC, ADC, DAC, Motion sensor and EEPROM. I2C communication is ideal for attaching low-speed peripherals to a motherboard or embedded system that require the reliable short distance communication.  I2C devices use only 2 pins i.e. SDA which is used to transfer the data between two chips and SCL which is used to synchronize  that data transfer.

I2C ( TWI ) in AVR : I2C is referred as Two-wire Serial Interface ( TWI ). In this section we will see how to program the AVR to address a slave device and send or receive data using TWI. 

Programming of the AVR TWI in Master operating mode :
To work in master operating mode, we must be able to initialize the TWI, transmit a START condition , send or receive data , and transmit a STOP condition. Now lets see the essential steps in details and same are implemented in our code.

Initialization : 
To initialize the TWI module to operate in master operating mode, we should do the following steps:
1. Set the TWI module clock frequency by setting the values of the TWBR register and the TWPS bits in the TWSR register.
2. Enable the TWI module by setting TWEN bit in TWCR register to one. 

Transmit START condition :
To start data transfer in master mode, we must transmit the START condition. This is done by setting TWEN, TWSTA and TWINT bits of TWCR  to one. 
Setting TWEN bit to one enables the TWI module. 
Setting TWASTA bit to one tells the TWI module to initiate the START condition when bus is free
Setting TWINT bit to one clears the interrupt flag to initiate the operation of TWI module to transmit START condition.
Then we should check the TWINT flag in TWCR register to see whether START condition transmitted completely.

Send Data :
To send a byte of data, after transmitting the START condition, following steps needs to be followed.
1. Copy the data byte to the TWDR
2. Set the TWEN and TWINT bits of TWCR register to one to start sending the byte data.
3. Observe the TWINT flag in the TWCR register to see whether the byte transmitted completely.

Note that right after the START condition, master should make sure that whether it wants to write or read from slave. For this purpose, i2c_write function is used. In this function master send
SLA + W(Slave Address + Write bit) or  SLA + R(Slave Address + Read bit). Right after sending SLA+W we should write to the slave and after sending SLA+R we should read from slave.

Receive Data :
As stated earlier, after transmitting SLA+R, master is ready to receive a byte of data. Following steps should be done
1. Set the TWEN and TWINT bits of TWCR register to one to start receiving a byte.
2. Check the TWINT flag in the TWCR register to see whether a byte is received completely.
3. Copy the received byte from TWDR to another register in order to save it.

Transmit STOP condition :
To stop data transfer, STOP condition must be transmitted. This is done by setting TWEN, TWSTO and TWINT bits of TWCR register to one.

Note : Follow the below github link to see the detailed codes for operating arduino in master mode for write as well as read application. 


Programming of the AVR TWI in Slave operating mode :
To work in slave operating mode, we must be able to initialize the TWI and able to send or receive data.
In slave mode, we cannot transmit START and STOP condition Now lets see the essential steps in details and same are implemented in our code.

Initialization:
1. Set the slave address by setting the value for TWAR register. The upper seven bits of TWAR register are address bits and eighth bit is TWGCE. If this bit is set to one , TWI module will respond to general call address otherwise it will ignore it.
2. Enable the TWI module by setting the TWEN bit in the TWCR register. 
3. Set the TWEN,TWINT and TWEA bits of TWCR register to one to enable TWI and acknowledgement generation.

Listen To The Bus:
After initializing the TWI module, a slave device should listen to the bus to detect when it is addressed by a master device. When TWI module detects its own address on the bus, it returns ACK and sets the TWINT flag to one. One should check the TWINT flag  to see when slave is being address by the master device.

Send Data :
After being addressed by the master, we should do following steps to send a byte of data.
1. Copy the data byte to the TWDR
2. Set the TWEN and TWINT bits of TWCR register to one to start sending the byte data.
3. Observe the TWINT flag in the TWCR register to see whether the byte transmitted completely.

Receive Data : 
After being addressed by the master, we should do following steps to receive a byte of data.
1. Set the TWEN and TWINT bits of TWCR register to one to start receiving a byte. If we want to return ACK after receiving the data , we should set the TWEA bit of the TWCR register to one.
2. Check the TWINT flag in the TWCR register to see whether a byte is received completely.
3. Copy the received byte from TWDR to another register in order to save it.

I2C communication between two Arduinos

In this example we will see the simulation in which one arduino to work as slave in write mode which sends char 'A' to master  and other arduino to work as master in read mode receives the input 
char 'A'  ( 01000001 ) and display its ASCII value on PORTD. 

 




        
In above fig ARD1 is Master in Read Mode and ARD2 is Slave in Write Mode.