1

Note: I'm using just the atmega chip and atmel studio. Not exactly a full arduino.

I have been using the atmega168 with a MAX17040 fuel gauge in a project. The I2C interface between the atmel and the fuel gauge is working fine and I am able to read data from the fuel gauge.

Due to the power requirement of the project, the fuel gauge requires its compensation value to be adjusted. This is a 16 bit register, so according to the manufacturer I have to write 0x1234 across address 0x0C and 0X0D in one go. Otherwise the values are discarded.

All the datasheet and online forums talk about 8-bit I2C addressing (which I have working), but instruction on addressing 16 bit register is limited. I was wondering if anyone can help me on this.

My basic code is pasted below. The I2C_start takes care of TWCR, TWDR, etc. It could be something to do with Repated_Start, but not sure.

uint8_t I2C_write_register(uint8_t device, uint8_t address, uint8_t value)
{
 device <<= 1;
 uint8_t ret = I2C_start(device | TW_WRITE);
 if (ret)
 return 1;
 if (!ret)
 ret = I2C_write(address);
 if (!ret)
 ret = I2C_write(value);
 I2C_stop();
 return ret;
}
uint8_t I2C_start(uint8_t address){
 // reset TWI control register
 TWCR = 0;
 // transmit START condition
 TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
 // wait for end of transmission
 while( !(TWCR & _BV(TWINT)) );
 // check if the start condition was successfully transmitted
 if((TWSR & 0xF8) != TW_START){ return 1; }
 // load slave address into data register
 TWDR = address;
 // start transmission of address
 TWCR = _BV(TWINT) | _BV(TWEN)|_BV(TWEA); //|_BV(TWEA) added
 // wait for end of transmission
 while( !(TWCR & _BV(TWINT)) );
 // check if the device has acknowledged the READ / WRITE mode
 uint8_t twst = TW_STATUS & 0xF8;
 if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
 return 0;
}
asked Apr 21, 2015 at 19:02
6
  • How does Wire not handle this already? Commented Apr 21, 2015 at 19:06
  • I should add, i'm not using a full arduino, just the atmega168 chip. And i'm using twi.h library from atmel studio. Commented Apr 21, 2015 at 19:13
  • So... then I don't understand why you asked this here. Commented Apr 21, 2015 at 19:14
  • Arduino and the atmega168 are essentially the same core. If the arduino can address 16-bit word over I2C, the atmega can do it too. Commented Apr 21, 2015 at 20:15
  • But why ask in the community where they use Wire, when your needs would be better served by a wider audience? Commented Apr 21, 2015 at 21:34

1 Answer 1

1

Ahh, was just able to solve it. Essentially, do not use TW_REPEATED_START. Just keep sending data 8 bit at a time. 1 bit at the beginning of each 8 bit will be lost, so make sure you shift them first.

Wire library uses a very similar concept for use with arduino.

uint8_t I2C_write_register(uint8_t device, uint8_t address, uint8_t value, uint8_t value)
{
 device <<= 1;
 uint8_t ret = I2C_start(device | TW_WRITE);
 if (ret)
 return 1;
 if (!ret)
 ret = I2C_write(address);
 if (!ret)
 ret = I2C_write(value);
 if (!ret)
 ret = I2C_write(value2);
 I2C_stop();
 return ret;
}
answered Apr 21, 2015 at 21:46

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.