1
\$\begingroup\$

So i am trying to establish a connection between ATMEGA328p as Master and 24LC256 EEPROM Chip using I2C protocol.

  • Clock is set to 100KHz
  • SDA and SCK lines are pulled up to Vcc using 4.7K Ohm resistors,
  • Start condition works fine, i get a ACK in return too,
  • ACK received when the right address is sent,
  • Fails when MSB of the address in the chip is sent!

Code:

#define FOSC         16000000UL
#define START        0x08
#define MT_SLA_ACK   0x18
#define MT_SLA_NACK  0x18
#define DEV_ADDR     0x50


typedef enum result_t{FAIL, SUCCESS}result;

void Debug_LED_ON()
{
   PORTD|=1<<PD4; //Turn on LED on PIN4 of PORTD
}

void set_clock(int freq_in_khz)
{
   TWCR = 1<<TWEN;     //Enable TWI module
   TWSR |=(1<<TWPS0); //Prescaler set to 4
   TWBR  = FOSC/freq_in_khz;
   TWBR -= 16;
   TWBR /= 8;  //2*Prescaler_value

}

void send_start()
{
   TWCR= ( (1<<TWINT) | (1<<TWEN) | (1<<TWSTA) ); //send START
   while( !(TWCR & (1<<TWINT)) ) ;                //wait for TWINT flag SET
}

void send_stop()
{
   TWCR= ( (1<<TWINT) | (1<<TWEN) | (1<<TWSTO) ); //send STOP
   //while( !(TWCR & (1<<TWINT)) ) ;                //wait for TWINT flag SET
}

result check_start_status()
{
   if ((TWSR & 0xF8) == START )
     return SUCCESS;
   else
     return FAIL;
}

void send_address(char addr_w)
{

   TWDR=addr_w; //7bit  address + W bit (write bit)
   TWCR = (1<<TWINT) | (1<<TWEN); //Clear TWINT bit to start transmission of address
   while (!(TWCR &(1<<TWINT)));  //wait for TWINT flag SET

}
result check_MT_slave_ack()
{
   if ((TWSR & 0xF8) == MT_SLA_ACK )
     return SUCCESS;
   else
     return FAIL;
}
result check_MT_slave_nack()
{
   if ((TWSR & 0xF8) == MT_SLA_NACK )
     return SUCCESS;
   else
     return FAIL;
}

void  transmit_data(char data)
{
   TWDR=data;
   TWCR = (1<<TWINT) | (1<<TWEN); //Clear TWINT bit to start transmission of Data on the bus
   while (!(TWCR &(1<<TWINT)));  //wait for TWINT flag SET

}

int main (void)
{
   DDRC=0xff;
   PORTC=0x30;   //Enable internal pullups on PORTC PINS  SDA(PC4) , SCL(PC5)
   DDRD=0xFF;   //Port D as output


   set_clock(100); //setting clock 100KHz
   send_start();

   if(check_start_status()==FAIL)
     Debug_LED_ON();


   send_address(DEV_ADDR << 1); 

   if(check_MT_slave_ack()==FAIL)
    Debug_LED_ON();

   transmit_data(0x00);  

   if(check_MT_slave_ack()==FAIL) //fails here!
    Debug_LED_ON();     

   return 0;
}

Guess somethings wrong with the code, or the way i send the address! A2,A1,A0 bits of 24LC256 are set to ground, therefore the device address is 0x50 << 1.

Update:

The device address is correctly sent now, now when i send the MSB of Address on the chip where i want to write data, it fails!

HW Setup

\$\endgroup\$
1
\$\begingroup\$

The value you are setting in send_address() function is one bit off. Chip address 0x50 is 7bit number, which has to be shifted 1 bit up when sending on I2C bus (lowest bit is read/write flag). So you should use send_address(0xa0) (that is 0x50<<1) in your code, or do the shift inside send_address() function.

By "when i send the Address+/W, i neither get ACK nor NACK" you mean that your code hangs in while (!(TWCR &(1<<TWINT))); loop inside send_address()? If so, than it is different issue unrelated to the address mentioned above.

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks! the code does not hang in send_address(). I was sending the address as a 7bit, 1010000, the upper nibble 1010 is fixed, now i get it! It works so far now, i.e i get an ACK in return :) \$\endgroup\$ – Abel Tom Jun 5 '17 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.