Let me clarify the "7-bit address issue of an I2C Slave device" and "8-bit data read/write issue" with the example of the following hardware setup (Fig-1).
Figure-1:
1. The I2C Bus is byte (8-bit) oriented system which means that data transfer/receive takes place one byte at a time.
2. The Slave in Fig-1 has been assigned the 7-bit I2C address as: 010 0011 (0x23).
3. Before wrirting a data byte (Say: 0x83) into the Slave, the Master makes a Roll Call of the Slave by sending its address (0100011).
4. Now, the question is: when the I2C bus handles 8-bit data, then how does it handle 7-bit address of the Slave device?
Ans: In data write mode (data goes from Master to Slave), the I2C Interface automatically places a zero (0) at the right-most position of the 7-bit Slave address to make it 8-bit. Thus, there is:
0100011 ==> 00100011 (0x23)
==> 01000110 (0x46) //This is what is being transmitted during write mode bus operation
5. The following codes take care of the situation of Step-4:
Wire.beginTransmission(0b0100011); //==> 01000110
Wire.write(0x83); //Master sends 8-bit data (10000011) to Slave
Wire.endTransmission();
6. In read mode (data comes from Slave to Master), the Master makes a Rolll Call of the Slave by putting a one (1) at the right most postion of the 7-bit address to make it 8-bit. Thus there is:
0100011 == 0010 0011 (0x23)
==> 01000111 (0x47)//This is what is being transmitted during read mode bus operation
7. The following codes take care of the situation of Step-6:
Wire.requestFrom(0b0100011, 1); //request to get 1-byte from Slave ; 01000111 = 0x47
8. Test Sketch:
(1) Master Sketch: //sends data 0x83 to Slave; gets 1-byte data (0x53) from Slave
#include<Wire.h>
void setup()
{
Serial.begin();
Wire.begin();
//---------------------------------
Wire.beginTransmission(0b0100011); //==> 01000110
Wire.write(0x83); //Master sends 8-bit data (10000011) to Slave
Wire.endTransmission();
//-------------------------------------
Wire.requestFrom(0b0100011, 1);
byte x = Wire.read()
Serial.println(x, HEX); //Serial Monitor -1 of Master shows 53
}
void loop()
{
}
(2) Slave Sketch: //Slave receives 0x83 from Master; Slave sends 0x53 to Master
#include<Wire.h>
volatile byte x;
volatile bool flag = false;
void setup()
{
Serial.begin();
Wire.begin(0b010001); //Slave address 0x23
//--------------------------------------------------------------
Wire.onReceive(receiveEvent); //ISR declaration
Wire.onRequest(sendEvent); //ISR declarion
}
void loop()
{
if(flag == true)
{
Serial.println(x, HEX); //Serial Monitor-2 of Slave shows: 83
flag = false;
}
}
void receiveEvent(int howMany)
{
x = Wire.read(); //x = 0x83
flag = true;
}
void sendEvent()
{
Wire.write(0x53);
}