I²C command clarification

Hi,

How to send read write bit in I²C command.

Example I would like to interface DS1307. In this case device address is 1101000 7bit.
In read mode 11010001.
In write mode 11010000.
But this Wire.beginTransmission(); this function transmit 7bit only. Then how can I send the R/W bit ?.
Wire.write(0); can I use this ?. For 8th lsb R/W bit.

beginTransmission does not transmit anything. The 8th bit is set depending on the action you take (read or write).

From Wire.cpp:

void TwoWire::beginTransmission(uint8_t address)
{
  // indicate that we are transmitting
  transmitting = 1;
  // set address of targeted slave
  txAddress = address;
  // reset tx buffer iterator vars
  txBufferIndex = 0;
  txBufferLength = 0;
}

Wire.beginTransmission() sets the R/W bit to 'write' for you.
Wire.requestFrom() sets the R/W bit to 'read' for you.

#include <Wire.h>

int address_write = 0b1101000;  //7bit only
int address_read = 0b11010001;
int control_register = 0b00000111;

void setup(){
  Wire.begin();
  Serial.begin(9600);
}

void loop(){
  Wire.beginTransmission(address_write); //7bit+0bit(lsb) I am correct ?.
  Wire.write(control_register); //8bit(0b00000111) I am correct ?.
  Wire.endTransmission(); //stop leave i2c bus. I am correct ?.
  Wire.requestFrom(address_write,1); //7bit+1bit(lsb) I am correct ?.
  while(Wire.available() == 0); //still wait wire buffer empty == 0 means empty I am correct ?.
  long data = Wire.read(); //read from slave and store into variable i am correct ?.
  Serial.println(data);
  delay(1000);
}

Now I am trying to read single byte from my DS1308 RTC in Datasheet Single byte read i2c pattern.

Start—11010000—Ack—00000111—Ack—Repeated Start—11010001—Ack—value—Nack—Stop

Is my arduino code is correct ?. Where I am mistake ?.

Questions:
1.beginTransmission(7bit ? or 8bit(r/w) ?);
2.Wire.write(Can I send single bit here ?.);
3.In data sheet said repeated start. How can I make repeated start ?.(avoid endTransmission(); ).
4.Wire.requestFrom(Same 7bit address ?., how many bytes I want from ?);
5.while(Wire.available()==0); This means what ?. what it does ?.
==0 means what?.
or just can I use while(Wire.available()); like this ?.

I have attached my output using proteus. i2c debugger and virtual terminal output.

Here I have attached my Proteus output.

Arduino uses the 7-bits I2C address that is shifted one position to the right.
You can find it by using the I2C scanner.

Is it the DS1307 or DS1308 ?
You know that there is an enormous amount of Arduino code for the DS1307 ? And that the chip is outdated ? And that the DS3231 is a lot better ?

You select the control register, and then you read its value. That is correct.

A few notes:

long data = Wire.read();

The 'long' is not normal. You are reading a 8-bits register from the DS1307. Make the variable a 'byte' and also a 'int' is okay.

while(Wire.available() == 0);

Remove that line please. There is no such thing as waiting for something. It is a common mistake and sadly you found the wrong example. After a Wire.requestFrom(), you can do a Wire.read().

Do not use address_write and address_read. Use a single variable for the DS1307. That is the 7-bits shifted I2C address which is 0b1101000 or 0x68.

#include <Wire.h>

byte address = 0b1101000;
byte control = 0b00000111;

void setup(){
  Wire.begin();
  Serial.begin(9600);
}

void loop(){
  Wire.beginTransmission(address);
  Wire.write(control);
  Wire.endTransmission(false); //restart
  Wire.requestFrom(address,1); //one byte request
  while(Wire.available()){
  int data = Wire.read();
  Serial.println(data);
  }
  delay(1000);
}

Wire.beginTransmission(address);

That is the 7-bits shifted I2C address which is 0b1101000 or 0x68.

Arduino uses the 7-bits I2C address that is shifted one position to the right.
You can find it by using the I2C scanner.

oh ok ok. Wire.beginTransmission(address); this Arduino function makes 8 bit into 7 bit correct ?. and after adding r/w bit. I little bit get knowledge

And finally I found how to restart without stop Wire.endTransmission(false); this line is makes restart correct ?.(see i2c debugger window)

while(Wire.available() == 0);
Remove that line please. There is no such thing as waiting for something. It is a common mistake and sadly you found the wrong example. After a Wire.requestFrom(), you can do a Wire.read().

and I removed the line while(Wire.available()==0); then I didn’t get nothing. in my serial monitor as you can see I got only 0 value. also see the pattern of the data in i2c debugger window.

I have attached screenshot See the i2c debugger and serial monitor in. I got only 0 value.

@SureshKumar2610

It appears to be a matter of great charm to see your interest in understanding the working principles of TWI (I2C) Bus. TWI Bus theory/practice could be learnt in an interesting and progressive way when we lay down the steps to be carried out in order to write a data byte (say 47 into the SEC Register of DS1307 RTC).

1. Conver PC4 and PC5 IO lines of ATmega328P of UNO into TWI Bus.
2. Enable TWI Bus Interrupt Logic.
3. Acquire TWI Bus by bring START condition onto the TWI Bus.
4. Check the presence of a TWI Bus Slave (DS1307) by calling its 7-bit address (0b1101000).
5. Set the address pointer of the Slave of Step-4 to point SEC Register by sending address of the SEC Register (0x00).
6. Send data byte (say, 47) to the slave in order to get it written into the SEC Register pointer by the address pointer.
7. Check that all the above events have happened correctly (optional).
8. Release the TWI Bus by bringing STOP condition on the Bus.

All the above steps are well executed with the help of the following Arduino High Level Commands under the Arduino IDE Platform (assume that DS1307 RTC has already been initialized):

#include<Wire.h>

void setup()
{
   Wire.begin();
   
   Wire.beginTransmission(0b1101000);   //Slave address is queued in buffer (where is R-W/ bit?); not yet sent!   
   Wire.write(0x00);                                //address of SEC Register is queued
   WIre.write(0x47);                                //data for SEC Register is queued
   Wire.endTrasmission();                       //all the above queued items are transmitted and Bus is Free 
}

void loop()
{

}

To trace the location of the R-W/ bit (here the write bit) and other related events, we need to transform the above High Level Commands into ATmega328’s Register Level Instructions which could be presented/discussed depending on the interest of the OP! (The Register Level instruction are a little bit cryptic!)

@SureshKumar2610, your code should work with a real Arduino board and a real DS1307.
I don't know if a DS1307 accepts a repeated start. Some chips can't use it, and for some chips it must be used.

I have never read on this forum that simulation software works well.
I have read many times that simulation software is not working.

That means according to what I read on this forum, the simulation software never works.
It is therefor a lot easier to try your code with real hardware than trying for hours (days, weeks) to make the simulation work.

The Digital Oscilloscope shows that the SDA is doing something. If that is from the Wire.requestFrom(), then the slave is responding with data.

It is perhaps not needed to dive deep into the Wire library as GolamMostafa is writing. However, it is good to know that the Wire.endTransmission() does all the start, writing data and the stop. It uses data from a buffer that was filled by Wire.write().

It is perhaps not needed to dive deep into the Wire library as GolamMostafa is writing.

When we look at the OP, we find that the poster is very much eager to know about the R-W/ bit of the 8-bit wide Control Byte composed of deviceAddress+dataDirectionBit (R-W/ bit). The diagram of Fig-1 is an example of a typical Control Byte of the TWI Bus Scheme.


Figure-1: layout of the bit structure of a typical Control Byte of TWI Bus

I have been tracking this thread, and I have been noticing the untiring involvement of @Koepel to keep the discussion of this thread going on. I showed my interest to get involved in order to provide some information from which the OP may get the clues of the physical existence of the Read/Write bit of the Control Byte. The following diagram of Fig-2 may help to grasp the role of Read(1)/Write(0) bit in the case of DS1307 RTC chip. The actual implementation mechanism can be understood with the help of Register level instructions.

Figure-2: Conceptual view of the input/output 3-state gates of DS1307 RTC Chip

When the 7-bit deviceAddress (upper 7-bit of the Control Byte) is matched, the decoder passes the R-W/ bit which selects either G1 (write mode) or G2 (read mode) as requested. Let us look at the following Register level instructions:

TWDR = 0b11010000;  //deviceAddress (0b1101000) + Write bit(0)
TWCR = 0b10000100; //TWI Bus remains enabled, TWINT flag gets cleared, START bit is OFF
while (bitRead(TWCR, 7) !=HIGH)  //check if transmission of TWDR's contents is finished; slave has generated ACK. 
    ;
byte x = (TWSR & 0b111111000);  //a value of 0x18 (ref: data sheets) in x indicates successful transmission; useful to raise error message/continue with next bus action.

When TWDR-Register is loaded with a value, the TWI Interface immediately generates 8-SCL pulses to transmit the 8-bit data of the TWDR (TWI Data Register, Fig-3) in serial fashion with MSBit first. It also genertaes one more SCL pulse (the 9th pulse) to sample ACK signal whic the slave creates bu pulling down the SDA line (Fig-4). The user program clears the TWINT flag, and then it goes to poll the TWINT flag (Bit-7 of TWCR Register) again to detect the end of the transmission session of just 1-byte data.

Figure-3: TWI Bus Register of ATmega328P MCU


Figure-4: TWI Bus timing diagram between Master and Slave (typical example) during device address inquiry