#include <avr/io.h>
#include <util/twi.h>
#define SLA_W 0b00111010 //the i2c adress of the acell WRITE
#define SLA_R 0b00111011 //the i2c adress of the accell READ
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
#define LONGBIT(x) ((unsigned long)0x00000001 << (x))
#define NOP asm("nop")
void twi_setup(void){
// PORTC|= (1<<PORTC5) | (1<<PORTC4); //enable pull ups on i2c bus
// DDRC |= (1<<DDC5) | (1<<DDC4); //port c outputs
TWSR|=(0<<TWPS1)|(0<<TWPS0); //presclaer 0
TWBR=0x02; // 0x02 with a presacler of 0 will give a feq of 400KHz
TWCR|=(1<<TWEN); //enable TWI
}
int16_t twi_read(uint8_t SUB)
{
uint8_t DATA;
//send ST and check for ST
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //send start
while (!(TWCR & (1<<TWINT))) // wait for status bits to indicate something was transmitted on the bus
;
if (TW_STATUS != TW_START){ //check status to see if it was a sucessful start transmission, 0x08
NOP;
return 1; //return, error
}
//send SAD+W and check for SAK
TWDR = SLA_W; //load READ adreess into register
TWCR = (1<<TWINT) | (1<<TWEN); //send it
while (!(TWCR & (1<<TWINT))) // wait for status bits to indicate something was transmitted on the bus
;
if (TW_STATUS != TW_MT_SLA_ACK){ //check to see if it was an ACK after the adress, 0x18
NOP;
return 2; //return, error
}
//send SUB and check for SAK
TWDR = SUB; //send dummy register
TWCR = (1<<TWINT) | (1<<TWEN); //send it
while (!(TWCR & (1<<TWINT))) // wait for status bits to indicate something was transmitted on the bus
;
if (TW_STATUS != TW_MT_DATA_ACK ){ //check to see if it was an ACK after the data, 0x28
NOP;
return 3; //return, error
}
//send SR and check for SR
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //send repeated start
while (!(TWCR & (1<<TWINT))) // wait for status bits to indicate something was transmitted on the bus
;
if (TW_STATUS != TW_REP_START){ //check to see if the repeated start send was good or not, 0x10
NOP;
return 4; //return, error
}
//send SAD+R and check for SAK
TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN); //send it
while (!(TWCR & (1<<TWINT))) // wait for status bits to indicate something was transmitted on the bus
;
if (TW_STATUS != TW_MR_SLA_ACK){ //check to see if it was an ACK recieved after the SLA+R adress, 0x40
NOP;
return 5; //return, error
}
TWCR = (1<<TWINT) | (1<<TWEN); //Start transmission to recieve the data from the salve
while (!(TWCR & (1<<TWINT))) // wait for status bits to indicate something was transmitted on the bus
;
DATA = TWDR; //load the returned data
if (TW_STATUS != TW_MR_DATA_NACK){ //check to see if the data was recieved and return with a NACK, 0x58
NOP;
return 6; //return, error
}
TWCR = (1<<TWINT) | (1<<TWSTO) | (0<<TWEN); //send a stop
return DATA;
}
I’m not using the same chip as you, but I’m pretty sure you have to mask off the bottom 3 bits of the status register before you check the status code against the tables in the data sheet. Here’s how I check status for successful data transmission:
if ((TWSR & 0b11111000) != 0x28)
{
// error code goes here
}
The bottom 2 bits are the prescaler value and the third bit flags an illegal write to TDWR, if I recall correctly. The values in the data sheet don’t include those 3 bits.