Related questions

0 votes
5 answers
0 votes
0 answers
asked Apr 21, 2017 in Embedded by Bindu Kulkarni
0 votes
0 answers
asked Aug 2, 2017 in SQL by anonymous
0 votes
0 answers

How to implement I2C communication protocol in Embedded C...

0 votes
asked Apr 20, 2017 in Embedded by anonymous

1 Answer

0 votes

Hello Chandrakanth,

-> I2C is a synchronous protocol because it uses SCL(serial clock line).

-> I2C consist of 2 wire SCL and SDA, SCL is used generate a clock pulses to differentiate between data bits, SDA is used for sending and receiving data.(To know the difference between Synchronous and Asynchronous communication please google it).

-> I2C consist of 2 types of addressing 7-bit and 10-bit addressing mode, in 7-bit addressing mode it can ability to connect 128 devices(0-127). in 10-bit addressing it can ability to connect 1008 devices.

-> I2C uses certain rules to communicate  with devices following steps will define the I2C connection establishment and send, receice the data.

1)  Start Sequence

2)  Address Frame

3)  Data Frame

4)  Stop Sequence

Start Sequence :  Before communicating with any devices in I2C protocol first we need to send start sequence. We should make SDA line to low and make SCL line to low then slave devices receives a start alert. start sequence is intiated by master.

Address Frame : after sending a start sequence then master sends the address of the slave with an R/W bit.the slave receive an address and R/W bit and the corresponding slave send ACK to the master.(R/W means whether master want to read a data from slave or write a data to the slave are mentioned here if R/W == 1 means read a data from slave  if it is R/W == 0 means master write a data to slave).

Data Frame : After receiving a positive ACK from slave master send the data frame to the slave(in the write operation master send the data frame to the slave, while in the read operation it will send the address to slave location to read the data).

Stop Sequence : After everything over it will send the stop sequence to the slave.

Only master initiate the stop and start sequence slave can't initiate or contact the master...

C Programming Over I2C

#define SCL     TRISB4 // I2C bus
#define SDA     TRISB1 //
#define SCL_IN  RB4    //
#define SDA_IN  RB1    //

To initialize the ports set the output resisters to 0 and the tristate registers to 1 which disables the outputs and allows them to be pulled high by the resistors.
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;


We use a small delay routine between SDA and SCL changes to give a clear sequence on the I2C bus. This is nothing more than a subroutine call and return.
void i2c_dly(void)
{
}

The following 4 functions provide the primitive start, stop, read and write sequences. All I2C transactions can be built up from these.
void i2c_start(void)
{
  SDA = 1;             // i2c start bit sequence
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 0;
  i2c_dly();
  SCL = 0;
  i2c_dly();
}


void i2c_stop(void)
{
  SDA = 0;             // i2c stop bit sequence
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 1;
  i2c_dly();
}

unsigned char i2c_rx(char ack)
{
char x, d=0;
  SDA = 1; 
  for(x=0; x<8; x++) {
    d <<= 1;
    do {
      SCL = 1;
    }
    while(SCL_IN==0);    // wait for any SCL clock stretching
    i2c_dly();
    if(SDA_IN) d |= 1;
    SCL = 0;
  } 
  if(ack) SDA = 0;
  else SDA = 1;
  SCL = 1;
  i2c_dly();             // send (N)ACK bit
  SCL = 0;
  SDA = 1;
  return d;
}

bit i2c_tx(unsigned char d)
{
char x;
static bit b;
  for(x=8; x; x--) {
    if(d&0x80) SDA = 1;
    else SDA = 0;
    SCL = 1;
    d <<= 1;
    SCL = 0;
  }
  SDA = 1;
  SCL = 1;
  i2c_dly();
  b = SDA_IN;          // possible ACK bit
  SCL = 0;
  return b;
}


The 4 primitive functions above can easily be put together to form complete I2C transactions. Here's and example to start an SRF08 ranging in cm:

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0x00);             // SRF08 command register address
i2c_tx(0x51);             // command to start ranging in cm
i2c_stop();               // send stop sequence

Now after waiting 65mS for the ranging to complete (I've left that to you) the following example shows how to read the light sensor value from register 1 and the range result from registers 2 & 3.

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0x01);             // SRF08 light sensor register address
i2c_start();              // send a restart sequence
i2c_tx(0xE1);             // SRF08 I2C address with R/W bit set

lightsensor = i2c_rx(1);  // get light sensor and send acknowledge. Internal register address will increment automatically.
rangehigh = i2c_rx(1);    // get the high byte of the range and send acknowledge.
rangelow = i2c_rx(0);     // get low byte of the range - note we don't acknowledge the last byte.
i2c_stop();               // send stop sequence

answered Apr 20, 2017 by anonymous
...