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;
}