Pages: [1]   Go Down
Author Topic: I2C sample code rewriting in Wire  (Read 971 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I got stuck in rewriting this in Wire. Following code is for reading data out of the IQS253 chip. I want adapt the code, so it is then implemented against the Wire library. Can somebody please help me?

Code:
unsigned char i2c_read_byte(unsigned char ack)
{
  unsigned char i, receive_byte = 0;
  I2C_DATA_IN_FLOAT;     // Set I2C DATA pin as input and floating
  wait(2);               // Wait two I2C clock cycles
  for (i = 8; i > 0; i--) // Loop and read 8 bits from I2C DATA pin
  {
    wait(2);             // Wait two I2C clock cycles
    I2C_CLK_IN_FLOAT;    // Set I2C CLK pin as input and floating
    while(!I2C_CLK_IN);  // Wait for I2C CLK line low (clock stretching)
    if (I2C_DATA_IN) receive_byte |= (1 << (i - 1)); //Read data from I2C DATA pin
    wait(1);             // Wait one I2C clock cycle
    I2C_CLK_OUT_PP_LOW;  // Set I2C CLK pin as output (push-pull) and floating
  }
  wait(1);               // Wait one I2C clock cycle
  if (ack == 0) I2C_DATA_IN_FLOAT; //
  else I2C_DATA_OUT_PP_LOW; //Send acknowledge if required
  wait(2);               // Wait two I2C clock cycles
  I2C_CLK_IN_FLOAT;      // Set I2C CLK pin as input and floating
  while(!I2C_CLK_IN);    // Wait for I2C CLK pin low (clock stretching)
  wait(2);               // Wait two I2C clock cycles
  I2C_CLK_OUT_PP_LOW;    // Set I2C CLK pin as output (push-pull) and floating
  wait(2);               // Wait two I2C clock cycles
  I2C_DATA_IN_FLOAT;     // Set I2C DATA pin as input and floating
  return receive_byte;
}
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 111
Posts: 5239
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is more or less what Wire.read()'s function is, although the actual code is part of Wire.requestFrom().

This code is a software implementation of the I2C bus if you don't have hardware support for it. The Wire library uses the hardware support the ATmega family offers.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi pylon,

Thank you for your answer. I saw that I posted the wrong code snippet.
The datasheet tells to handle readings as follows:
- Send control byte with LSB = 0
- Send memory address
- Generate restart
- Send control byte with LSB = 1
- Read register value

How can this be done with Wire?

Screenshot of the relevant section in the datasheet:
http://www.picfront.org/d/8RO6
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 111
Posts: 5239
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is a standard I2C behavior. So it's more or less:

Code:
#define DEVICE_ADDRESS 0x47 // just an example, has to be changed for actual device
byte get_register(byte memory_address) {
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write(memory_address);
  Wire.endTransmission();
  Wire.requestFrom(DEVICE_ADDRESS, 1);
  if (Wire.available() > 0) {
    return Wire.read();
  }
  return 0;
}

The low-level stuff is handled by the Wire library and the underlying hardware. As in your example code control byte is device_address << 1 and here DEVICE_ADDRESS is control byte >> 1, you can directly set the device address (which is 7-bit).
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Unfortunately the code does not work. There's always a "0" returning.
Where do I have to write the control bytes?
And how can a repeated start be done?
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 111
Posts: 5239
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Unfortunately the code does not work. There's always a "0" returning.

Which one? Mine? That wasn't intended to work, it was just an example. For example the address was just a random number. You have to modify or at least provide a link to the datasheet of your device, so we have a chance to get the necessary information.

Quote
Where do I have to write the control bytes?

The control bytes are the address plus read/write bit, so they are in the code already.

Quote
And how can a repeated start be done?

Does that mean a start condition without a stop condition? Else you have to define it.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now it works. I didn't know that read/write bits are set by the library. Another problem was the endTransmission. In Arduino v1.0.1 this method can be called with the false flag. So no stop condition is sent.

Device address is 0x44.

Code:
byte get_register(byte memory_address) {
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write(memory_address);
  Wire.endTransmission(false);
  Wire.requestFrom(DEVICE_ADDRESS, 1);
  if (Wire.available() > 0) {
    return Wire.read();
  }
  return 0;
}

Thanks again for your help.
Logged

Pages: [1]   Go Up
Jump to: