Transfer and receive data on the i2c bus

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
8 bit mcu sends the data value to the seconds register of ds1307 according to the i2c protocol.

You can see a picture diagram of the process below

leangth.jpg

I'm sure the master is sending three bytes and receiving three bits on the i2c bus

What happens in the Start and Stop Boxes.

Is data transfer or data received in those boxes?
 

JohnInTX

Joined Jun 26, 2012
4,787
No data is transferred in Start and stoP. Those are special combinations of SDA and SCL to frame one I2C message. Those conditions have other uses as well when more than one master is on the bus.

Here is the spec for I2C written by the people who invented it. It will tell you everything you need to know.
The datasheet for the DS1307 shows in detail the I2C messages necessary to use it. The diagrams are not the best but they are accurate.

There are also many threads here on AAC discussing I2C. Check them out as well. Here's a recent one but there are many.
https://forum.allaboutcircuits.com/threads/pic-development-board-with-pk3.172494/post-1566093

Read up and have fun!
 

Attachments

Last edited:

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
No data is transferred in Start and stoP. Those are special combinations of SDA and SCL to frame one I2C message. Those conditions have other uses as well when more than one master is on the bus.

Here is the spec for I2C written by the people who invented it. It will tell you everything you need to know.
The datasheet for the DS1307 shows in detail the I2C messages necessary to use it. The diagrams are not the best but they are accurate.
Question is only for general i2c protocol so i didn't name any specific microcontroller.

Please look at figure 3 in the datasheet.

Start condition generate when SDA goes from high to low. When SCL is high.

Stop condition generate when SDA goes from low to high. When SCL is high.

It seems to me that the master continuously sends serial clock pulses so the slave device. When Clock goes High and SDA is low it means there is no communication. When clock goes high and SDA become High it means that communication has started.

The points is, when the clock goes high and there is 5 volts on the SDA pin, a start condition is generated. when the clock goes high and there is 0 volts on the SDA pin, a stop condition is generated.

Is this the point of start and stop condition?

Does the master continuously send pulses or are they sent only when it is required?
 
Last edited:

Ian0

Joined Aug 7, 2020
9,803
Does the master continuously send pulses or are they sent only when it is required?
No, only when required. The slave is also capable of driving the clock line, it can slow the master down if it is going too fast by holding the clock low until it is ready.
The points is, when the clock goes high and there is 5 volts on the SDA pin, a start condition is generated. when the clock goes high and there is 0 volts on the SDA pin, a stop condition is generated.
That's wrong. The start and stop are generated by a change in state on SDA whilst clock is high. SDA may not normally change state whilst clock is high, that it what differentiates start and stop conditions from a normal data bit.

If your microprocessor doesn't have a built-in IIC interface, it's easy to write one in software by controlling the data lines directly. I use that technique on NXP LPC microcontrollers because it is actually takes LESS code to do it that way than by using their built-in interface.
 

Papabravo

Joined Feb 24, 2006
21,225
Question is only for general i2c protocol so i didn't name any specific microcontroller.

Please look at figure 3 in the datasheet.

Start condition generate when SDA goes from high to low. When SCL is high.

Stop condition generate when SDA goes from low to high. When SCL is high.

It seems to me that the master continuously sends serial clock pulses so the slave device. When Clock goes High and SDA is low it means there is no communication. When clock goes high and SDA become High it means that communication has started.

The points is, when the clock goes high and there is 5 volts on the SDA pin, a start condition is generated. when the clock goes high and there is 0 volts on the SDA pin, a stop condition is generated.

Is this the point of start and stop condition?

Does the master continuously send pulses or are they sent only when it is required?
The master DOES NOT SEND clock pulses continuously. The purpose of having the primary device do this is because it controls the state of both SCL and SDA, and can use this feature to make certain that all of the peripheral devices that are on the bus are in the SAME state at the beginning of the transaction. Furthermore, if SCL and SDA are not in the correct state for performing a START operation the can be placed in the correct state for doing that. Similarly for a STOP condition, the SDA and SCL lines can be made to execute the stop condition regardless of where they have previously been. The protocol engine completely RESETS itself between each and every data transfer transaction.

START <one or more bytes> STOP, wash rinse, repeat.
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
That's wrong. The start and stop are generated by a change in state on SDA whilst clock is high. SDA may not normally change state whilst clock is high, that it what differentiates start and stop conditions from a normal data bit.
Let's say clock goes High for 2us and goes low for 2us.

When SDA change state from High to low within 2us ( clock high for 2us ) then start condition is generated.

When SDA change state from low to high within 2us ( Clock High for 2us) then stop condition is generated.

Is my point valid now ?
 

Ian0

Joined Aug 7, 2020
9,803
Let's say clock goes High for 2us and goes low for 2us.

When SDA change state from High to low within 2us ( clock high for 2us ) then start condition is generated.

When SDA change state from low to high within 2us ( Clock High for 2us) then stop condition is generated.

Is my point valid now ?
That's correct.
 

Papabravo

Joined Feb 24, 2006
21,225
If these are the rules:
Start condition generate when SDA goes from high to low. When SCL is high.
Stop condition generate when SDA goes from low to high. When SCL is high.
Then a logical corollary is that SDA should not change when SCL is HIGH. The data on SDA changes only when SCL is low and therefore avoids making the bus lines look like a START condition or a STOP condition.
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
That's correct.
This mean we have to always configure SDA and SCL pin in program to generate START and STOP condition

C:
void I2C_START ()
{
    if ( SCL == High )
        {
           SDA = High;
           wait_us (1);
           SDA = Low ;
        }
}

void I2C_STOP ()
{
    if ( SCL == High )
        {
           SDA = Low;
           wait_us (1);
           SDA = High ;
        }
}
its for software I2C

EDIT - Theoretically what we have discussed yet for start and stop condition,
Do both my functions show this ?
 
Last edited:

Ian0

Joined Aug 7, 2020
9,803
This mean we have to always configure SDA and SCL pin in program to generate START and STOP condition

C:
void I2C_START ()
{
    if ( SCL == High )
        {
           SDA = High;
           wait_us (1);
           SDA = Low ;
        }
}

void I2C_STOP ()
{
    if ( SCL == High )
        {
           SDA = Low;
           wait_us (1);
           SDA = High ;
        }
}
its for software I2C

EDIT - Theoretically what we have discussed yet for start and stop condition,
Do both my functions show this ?
You should start by setting SCL high, because if it's not already high you could wait for ever. Then check to see if it is high, because it's an open-collector bus, and the peripheral could be holding it low.
Also, don't forget to configure your SCL and SDA pins as open-drain. Or, if your processor is a PIC, you set the pin permanently to LOW and you change the state by switching the pin from input to output. When it is an input, the pull-up resistor pulls it high and when it's an output the pin pulls it low.
When initialising the program make sure that SCL and SDA are initialised to a high state, otherwise the peripherals won't respond to the first bus transaction (got caught out with that one just yesterday).
[edit] and don't forget the pull-up resistors!
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
You should start by setting SCL high, because if it's not already high you could wait for ever. Then check to see if it is high, because it's an open-collector bus, and the peripheral could be holding it low.
Also, don't forget to configure your SCL and SDA pins as open-drain. Or, if your processor is a PIC, you set the pin permanently to LOW and you change the state by switching the pin from input to output. When it is an input, the pull-up resistor pulls it high and when it's an output the pin pulls it low.
When initialising the program make sure that SCL and SDA are initialised to a high state, otherwise the peripherals won't respond to the first bus transaction (got caught out with that one just yesterday).
[edit] and don't forget the pull-up resistors!
We transfer 8 bits of data on the i2c bus once the start condition is generated. There is one clock pulse per bit of data. The datasheet shows that the master sends 8 clock pulses to the slave to send 1 byte of data. If SDA is set at 9th clock it means that the slave has accepted the address.

it seems to me that slave send 1 bit of data to master at 9th clock. If master sends correct address of slave then slave will send bit value 0 to master and if master sends wrong address of slave then slave will send bit value 1 to master and communication must stop

Do slave transfer 1 bit of data to master at 9th clock?
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
Do slave transfer 1 bit of data to master at 9th clock?
Yes but it is probably better to think of that one bit as what it is, a signal that the slave has received a byte from the master and can receive another byte. 'Data' implies that there is some variable value that the master will use. Things like ACK/NACK are just signals to proceed or quit sending more data.

After the 8th data bit, the master releases SDA and for ONE clock, SDA is controlled by the slave. ACK is generated by the slave actively pulling SDA down during the 9th clock. After that, the slave releases SDA and the master takes control of SDA for the next byte.

If there is no slave, there is nothing to pull down SDA so it remains at a '1' during the 9th clock and the master again knows to not send any more data.
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
Yes but it is probably better to think of that one bit as what it is, a signal that the slave has received a byte from the master and can receive another byte. 'Data' implies that there is some variable value that the master will use. Things like ACK/NACK are just signals to proceed or quit sending more data.
It seems to me earlier function can be improved more
C:
# define ACK      0
# define NACK     1

// Function to start I2C communication
void I2C_START ()
{
   // SDA and SCL should be High in ideal condition
   SCL = High ;
   SDA = High ;

// Set SDA to LOW, while the clock  is  HIGH to generate START condition
  if ( SCL == High )
    {
       SDA = Low ;
    }
   wait_us(1);
   SCL = Low ;
}

// Function to stop I2C communication
void I2C_STOP ()
{
   SCL = High ;
  if ( SDA == High )
      {
        SDA = Low ;
      }
// Set SDA to HIGH, while  the  clock  line  is  HIGH
   if ( SCL == High )
     {
        SDA = High ;
     }

     wait_us(1);
     SCL = Low ;
}

// Function to send one byte to slave device
void I2C_Send(unsigned char Byte)
{
   unsigned char i;

   for( i = 0; i < 8; i++)
   {
        if ((Byte & 0x80 ) == 1)
        {
            SDA = High ; // Set SDA to High
            wait_us(1);
        }
      
        else
        {
            SDA = Low; // Set SDA to Low
        }
    
        Byte = (Byte << 1);  // shift the next bit
  
        SCL = High ;
        wait_us(1);
        SCL = Low;
    }
}

//Function to get ACK/ NACK from slave
unsigned char Get_ACK_NACK ()
{
    SCL = High ;
    if ( SDA == Low)
         return ACK;
    else
        return NACK;
}
Edit 1 - including function to get ACK/ NACK from slave

Edit 2- including function to send one byte to slave
 
Last edited:

Papabravo

Joined Feb 24, 2006
21,225
START and STOP conditions should not have ANY conditional statements in them.

START:
SDA = High ;
SCL = High ;
SDA = Low ;
<short delay>
RETURN

STOP:
SDA = Low ;
SCL = High ;
SDA = High ;
<short delay>
RETURN ;

There are no conditions that you want to test when START OR STOP, and you don't want to do nothing, and you most certainly do not wan to wait for ANY event that may never happen. You want to establish the conditions for a START or a STOP right now -- without delay.

One more thing. Many embedded processors have an embedded I2C engine. In such a processor there will be methods for doing all of this without the need to bit-bang. Be sure you KNOW which environment you are operating in.
 
Last edited:

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
START and STOP conditions should not have ANY conditional statements in them.
I thought It would be a good idea to check the conditions in START and STOP.

START:
SDA = High ;
SCL = High ;
SDA = Low ;
<short delay>
I think this short delay depends on the slave. What would be short delay for DS1307

One more thing. Many embedded processors have an embedded I2C engine. In such a processor there will be methods for doing all of this without the need to bit-bang. Be sure you KNOW which environment you are operating in.
What is the advantage of inbuilt I2C peripheral in mcu when mcu can communicate with slave device using software I2C?
 

Papabravo

Joined Feb 24, 2006
21,225
I thought It would be a good idea to check the conditions in START and STOP.



I think this short delay depends on the slave. What would be short delay for DS1307



What is the advantage of inbuilt I2C peripheral in mcu when mcu can communicate with slave device using software I2C?
A short delay could be like a single NOP instruction. The purpose is to ensure there are no timing violations when you combine the START and STOP operations with other operations, and to make sure your SCL frequency does go faster than the maximum clock rate. It may not be necessary in some cases.

The advantage to an I2C engine in hardware is that you can setup the I2C transaction, go do something else, and have the I2C engine notify you when the operation is complete. You also don't have to worry about disabling interrupts while you are using the processor to do precise low level bit timing operations.
 

Ian0

Joined Aug 7, 2020
9,803
The advantage to an I2C engine in hardware is that you can setup the I2C transaction, go do something else, and have the I2C engine notify you when the operation is complete. You also don't have to worry about disabling interrupts while you are using the processor to do precise low level bit timing operations.
I wish that were always true. Microchip has nice I2C hardware that can be left to get on with it and do a whole byte. NXP's needs attention every bit. (Surely they can manage better - they invented it - their new micro has a fantastic A/D that can manage a whole sequence of different measurements all on its own, but I2C = 10 interrupts per byte) I rewrote my code to drive the output lines directly and the new code was a dozen lines shorter.
Because I2C doesn't have a fixed baud rate, if the transaction gets interrupted then it can just come back and complete it when the interrupt routine is finished.
 

dcbingaman

Joined Jun 30, 2021
1,065
If your microcontroller does not have a built in I2C interface another easy method to implement that is to add a very small CPLD to your board design to handle I2C. I2C is easily implemented in VHDL/Verilog.
 
Top