I2C stands for Inter-Integrated Circuit. It is a serial communication protocol which allows for multiple masters and multiple slaves. It was invented by NXP Semiconductors.
I2C uses two bi-directional open drain lines ,SDA (Serial Data Line) and SCL(Serial Clock Line), pulled up with resistors.
The maximum number of nodes is limited by the address space and also by the total bus capacitance, which restricts communication distances to a few metres.
Master Node generates the clock and initiates communication with slaves.
Slave Node receives the clock and responds when addressed by master.
Multi-Master , Multi-slave bus means that any number of master and slave nodes can be present. Master and slave nodes may interchange roles between messages.
There may be four potential modes of operation for a given bus device, although most devices only use a single role and its two modes:
If the slave exists on the bus then it will respond with an ACK bit (active low for acknowledged) for that address. The master then continues in either transmit or receive mode (according to the read/write bit it sent), and the slave continues in its complementary mode (receive or transmit, respectively).
APPLICATIONS :
I2C is used in embedded systems application where simplicity and manufacturing costs outweigh the need of high speed.
1. Reading configuration data from SPD EEPROMs, SDRAM , DDR SDRAM
2. Accessing Low speed ADCs and DACs
3.Controlling OLED/LCD displays, like in a cellphone.
4.Reading Real Time Clocks.
5.Turning on and turning off the power supply of system components.
A particular strength of I2C is the capability of the micro controller to control a host of devices woth just two general purpose I/O pins and software. Many other bus technologies such as SPI, require more pins and signals to connect devices.
CODE
#define F_CPU 16000000UL // Clock speed
#include <avr/io.h>
#include <util/delay.h>
#include <util/twi.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_TRIES 50
#define BAUD 9600 //Baud Rate:9600
#define BAUD_PRESCALE (((F_CPU / (BAUD * 16UL))) - 1)
void TWI_start(void);
void TWI_repeated_start(void);
void TWI_init_master(void);
void TWI_write_address(unsigned char);
void TWI_read_address(unsigned char);
void TWI_write_data(unsigned char);
void TWI_read_data(void);
void TWI_stop(void);
void USART_send( unsigned char );
void USART_init(void);
int main(void)
{
USART_init();
TWI_init_master();
while(1)
{
// Your Application code
// Using the functions below, you can make your own read and write frames to suit different
devices
}
}
// Clear TWI interrupt flag, Put start condition on SDA, Enable
TWI
I2C uses two bi-directional open drain lines ,SDA (Serial Data Line) and SCL(Serial Clock Line), pulled up with resistors.
The maximum number of nodes is limited by the address space and also by the total bus capacitance, which restricts communication distances to a few metres.
Master Node generates the clock and initiates communication with slaves.
Slave Node receives the clock and responds when addressed by master.
Multi-Master , Multi-slave bus means that any number of master and slave nodes can be present. Master and slave nodes may interchange roles between messages.
There may be four potential modes of operation for a given bus device, although most devices only use a single role and its two modes:
- master transmit — master node is sending data to a slave
- master receive — master node is receiving data from a slave
- slave transmit — slave node is sending data to the master
- slave receive — slave node is receiving data from the master
If the slave exists on the bus then it will respond with an ACK bit (active low for acknowledged) for that address. The master then continues in either transmit or receive mode (according to the read/write bit it sent), and the slave continues in its complementary mode (receive or transmit, respectively).
APPLICATIONS :
I2C is used in embedded systems application where simplicity and manufacturing costs outweigh the need of high speed.
1. Reading configuration data from SPD EEPROMs, SDRAM , DDR SDRAM
2. Accessing Low speed ADCs and DACs
3.Controlling OLED/LCD displays, like in a cellphone.
4.Reading Real Time Clocks.
5.Turning on and turning off the power supply of system components.
A particular strength of I2C is the capability of the micro controller to control a host of devices woth just two general purpose I/O pins and software. Many other bus technologies such as SPI, require more pins and signals to connect devices.
CODE
#define F_CPU 16000000UL // Clock speed
#include <avr/io.h>
#include <util/delay.h>
#include <util/twi.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX_TRIES 50
#define BAUD 9600 //Baud Rate:9600
#define BAUD_PRESCALE (((F_CPU / (BAUD * 16UL))) - 1)
void TWI_start(void);
void TWI_repeated_start(void);
void TWI_init_master(void);
void TWI_write_address(unsigned char);
void TWI_read_address(unsigned char);
void TWI_write_data(unsigned char);
void TWI_read_data(void);
void TWI_stop(void);
void USART_send( unsigned char );
void USART_init(void);
int main(void)
{
USART_init();
TWI_init_master();
while(1)
{
// Your Application code
// Using the functions below, you can make your own read and write frames to suit different
devices
}
}
void USART_init(void)
{
UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
UBRR0H = (BAUD_PRESCALE >> 8);
UBRR0L = BAUD_PRESCALE;
}
void USART_send(unsigned char data)
{
while(!(UCSR0A & (1<<UDRE0)));
UDR0 = data;
}
void TWI_init_master(void) // Function to initialize master
{
TWBR=0x48; // Bit rate
TWSR=(0<<TWPS1)|(0<<TWPS0); // Setting prescalar bits
// SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}
void TWI_start(void)
{
// Clear TWI interrupt flag, Put start condition on SDA, Enable
TWI
TWI
TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
// Wait till start condition is transmitted
// Wait till start condition is transmitted
while((TWSR & 0xF8)!= TW_START)USART_send('e');
// Check for the acknowledgement
// Check for the acknowledgement
}
void TWI_repeated_start(void)
{
// Clear TWI interrupt flag, Put start condition on SDA, Enable
TWI
TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
// Wait till start condition is transmitted
// Wait till start condition is transmitted
while((TWSR & 0xF8)!= TW_REP_START);
// Check for the acknowledgement
// Check for the acknowledgement
}
void TWI_write_address(unsigned char data)
{
TWDR=data;// Address and write instruction
TWCR=(1<<TWINT)|(1<<TWEN);
// Clear TWI interrupt flag,Enable TWI
// Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT)));
// Wait till complete TWDR byte transmitted
// Wait till complete TWDR byte transmitted
while((TWSR & 0xF8)!= TW_MT_SLA_ACK)USART_send('e');
// Check for the acknowledgement
//USART is used for debugging
// Check for the acknowledgement
//USART is used for debugging
}
void TWI_read_address(unsigned char data)
{
TWDR=data; // Address and read instruction
TWCR=(1<<TWINT)|(1<<TWEN);
// Clear TWI interrupt flag,Enable TWI
// Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT)));
// Wait till complete TWDR byte received
// Wait till complete TWDR byte received
while((TWSR & 0xF8)!= 0x40);
// Check for the acknowledgement
// Check for the acknowledgement
}
void TWI_write_data(unsigned char data)
{
TWDR=data; // put data in TWDR
TWCR=(1<<TWINT)|(1<<TWEN);
// Clear TWI interrupt flag,Enable TWI
// Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT)));
// Wait till complete TWDR byte transmitted
// Wait till complete TWDR byte transmitted
while((TWSR & 0xF8) != TW_MT_DATA_ACK);
// Check for the acknowledgement
// Check for the acknowledgement
}
void TWI_read_data(void)
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
// Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT)));
// Wait till complete TWDR byte transmitted
while((TWSR & 0xF8) != TW_MR_DATA_ACK);
// Check for the acknowledgement
}
void TWI_read_dataN(void)
{
TWCR = (1<<TWINT)|(1<<TWEN);
// Clear TWI interrupt flag,Enable TWI
while (!(TWCR & (1<<TWINT)));
// Wait till complete TWDR byte transmitted
while((TWSR & 0xF8) != TW_MR_DATA_NACK);
// Check for the acknowledgement
}
void TWI_stop(void)
{
// Clear TWI interrupt flag, Put stop condition on SDA, Enable
TWI
TWI
TWCR= (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
while(!(TWCR & (1<<TWSTO)));
// Wait till stop condition is transmitted
// Wait till stop condition is transmitted
}