Wire.requestFrom -details of function

Hi, I was trying to find details about Wire.requestFrom function. Library description is very light. not giving so much details and frankly going over code of function doesn't revealed so much. I'm trying to go more "bare metal" code and connecting DS3231 RTC via I2C. I was copying following code:

Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0); // set DS3231 register pointer to 00h Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); //Original

Wire.beginTransmission(DS3231_I2C_ADDRESS); *second = bcdToDec(Wire.read() & 0x7f); Wire.beginTransmission(DS3231_I2C_ADDRESS); *minute = bcdToDec(Wire.read()); Wire.beginTransmission(DS3231_I2C_ADDRESS); *hour = bcdToDec(Wire.read() & 0x3f); Wire.beginTransmission(DS3231_I2C_ADDRESS); *dayOfWeek = bcdToDec(Wire.read()); Wire.beginTransmission(DS3231_I2C_ADDRESS); *dayOfMonth = bcdToDec(Wire.read()); Wire.beginTransmission(DS3231_I2C_ADDRESS); *month = bcdToDec(Wire.read()); Wire.beginTransmission(DS3231_I2C_ADDRESS); *year = bcdToDec(Wire.read()); Wire.endTransmission();

I decoded whole code with exception of line with Wire.requestFrom. Can someone know in details, what is this function doing in detail?

Thx

Jozef

Have you ever seen using the functions of the Wire library in that way ?

I will talk about the "Wire.requestFrom()" from the Arduino Wire library for AVR microcontrollers (for example the Arduino Uno). The Wire.requestFrom() is only called by an Arduino which is the Master on the I2C bus. The Wire.requestFrom() does a complete I2C transaction, with START, STOP, reading databytes, everything.

  • First it sends a START
  • Then it puts the I2C address on the bus with the "read" bit in the lowest bit.
  • It checks the acknowledge from the Slave, if there is a acknowledge, then continue with reading data bytes.
  • It reads a byte and give an acknowledge to the Slave for the next byte. It puts the read byte in a buffer (inside the Wire library).
  • After the last byte is read, it does not send a acknowledge. Sending "no acknowledge" is the same as a NACK.
  • It sends a STOP.

That's it. After calling the Wire.requestFrom(), the read data is in a buffer inside the Wire library. The activity on the I2C bus has finished.

You can read those bytes from that buffer with Wire.read(), and Wire.available() tells how many bytes are still in that buffer.

The Arduino reference about the Wire library caused a lot of confusion in the past, so I made an alternative explanation.

Is this enough detail, or do you want to know about that the Wire library is interrupt-driven, but the Wire.requestFrom() is still blocking ?

I’m trying to go more “bare metal” code

To do that, it is a good idea to have an understanding of how I2C works.

I was copying following code

Written by someone who does not understand either the code, or how I2C works.

hi, thank you Koepel for explanantion on functionality. Real eye opener. I was under impression about I2C activity in wire.read(). now is making sense. Regrading program, I'm planning to use pooling instead interrupt for this one. But if you are will to share information on interrupt approach, I will appreciate it.

Thank you jremington for raising some points from my post. I read about I2C, follow programs on Arduino, which I showed and try extrapolate for bare metal from it. Maybe it was wrong approach, for future I should try I2C + CPU documentation first. I always learn, at least is it evidence I still not old. :)

Program worked well for me, so I didn't have reason to doubt it when doing reverse engineering.

When you use the interrupt signal, then you can make a interrupt routine that sets a flag. In the loop() you can read that flag. That is a common practice with the 'dmp' and FIFO.

volatile bool dmpTrigger;

void setup()
{
  attachInterrupt(digitalPinToInterrupt(pin), myISR, RISING)
}

void loop()
{
  if( dmpTrigger)
  {
    // There is something in the FIFO. Read data from the MPU-6050 FIFO.
    ...

    dmpTrigger = false;
  }
}

void myISR()
{
  dmpTrigger = true;
}

You can see that here: https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/MPU6050/examples/MPU6050_DMP6/MPU6050_DMP6.ino. It is not easy to implement. That i2cdevlib also has many issues, for example: using the Wire library in the wrong way.

Thank you Koepel again. Now many I2C is much clearer.

I will conclude this thread as resolved.

jozefvelky: I'm trying to go more "bare metal" code and connecting DS3231 RTC via I2C. I was copying following code:

When you have asked for 'bare metal' code -- what have you wanted to mean?

Are you asking for 'Register Level' codes for 'Wire.requestFrom()', which might give more details on how the 'data reception' process by the Master happens by 'TWI_Interrupt Mechanism'? If so, you have not got it yet; therefore, it is not the right moment to declare the thread 'resolved'.