Need help with using TWI to read data

Hi all,

I’ve been trying to familiarize myself with the Two Wire interface by writing a small program to read and write data to a 24AA external EEPROM chip. However I’m having some trouble reading data from the chip - After reading a single byte the Master Reciever sends a NACK, instead of an ACK, terminating the exchange.

The Datasheet was a little unclear on how to configure the Control Register once Master Rcv mode is activated. The code I’ve written so far is posted below:

#define MRC_DATA_ACK 0x50
#define MRC_DATA_NACK 0x58

int data_read(uint8_t read_len, char *buffer_ptr){
   
    Serial.print("Reading ");
    Serial.println(read_len);
    for(int i=0;i<=(read_len-1);i++)                // get bytes-1
    {
      TWCR=(1<<TWINT)|(1<<TWEN);         // set CR to recv data & send ACK
      while(!(TWCR & (1<<TWINT))){ ; }        // wait for interrupt
      buffer_ptr=(char )TWDR;                      // read data from reg
      *buffer_ptr++;                                      // increment ptr
      if((TWSR & 0xF8) != MRC_DATA_ACK){            // check  status register 
        Serial.print("Error. Status = 0x");                      // error catch
        Serial.print((TWSR & 0xF8), HEX);
        return (TWSR & 0xF8);
      }
    }
    TWCR=(1<<TWINT);                                  //  recv data & send NACK
    while(!(TWCR & (1<<TWINT))){ ; }                // check int set
    buffer_ptr=(char )TWDR;                              // read data from reg
    if((TWSR & 0xF8) != MRC_DATA_NACK){     // check status
        return (TWSR & 0xF8);
      }
    return 0;                                    // return ok
}

It should send an ‘ACK’ for each byte in the loop, then exit the loop, recv. the last byte then send a NACK. I’m setting the Control Register values based on the Datasheet (Master Receive status codes table), however after a single byte the function returns the error condition and says the Value 0x58 (Recvd data & sent NACK) is in the status register.

I’m pretty sure the problem is in the Control Register values, but I have no idea why it’s sending the nack insead of ack. For posterity, am programming on an ATMega2560 and interfacing with a 24AA512 EEPROM chip.
Any help would be great, thanks!

Have you tried just using the wire library?

The other thing you'll want to get your hands on is the Atmel application note AVR315 and accompanying code.

DKWatson:
The other thing you'll want to get your hands on is the Atmel application note AVR315 and accompanying code.

Huh, didn't know about these application notes - they're going to be really useful, thanks!

Did you find it?

Yes I found it, thanks - also found the solution to my problem! Dug through the source code looking at how they were reading and found an additional flag set. Added it, and everything worked! Thanks again.

for anyone interested the function above should set the flags
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA); for the first n-1 bytes, then clear TWEA for the last.