I2C-ATMEGA328p como Maestro y 24LC256 como esclavo

0

Así que estoy tratando de establecer una conexión entre ATMEGA328p como Maestro y el Chip EEPROM 24LC256 usando el protocolo I2C.

  • El reloj está configurado a 100KHz
  • Las líneas SDA y SCK se llevan a Vcc con resistencias de 4.7K Ohm,
  • La condición de inicio funciona bien, también recibo un ACK,
  • ACK recibido cuando se envía la dirección correcta,
  • ¡Falla cuando se envía el MSB de la dirección en el chip!

Código:

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

Adivina algunas cosas mal con el código, o la forma en que envío la dirección! A2, A1, A0 bits de 24LC256 se ponen a tierra, por lo tanto, la dirección del dispositivo es 0x50 < < 1.

Actualización:

La dirección del dispositivo se envía correctamente ahora, ahora cuando envío el MSB de dirección en el chip donde quiero escribir los datos, ¡falla!

    
pregunta Abel Tom

1 respuesta

0

El valor que está configurando en la función send_address() está desactivado un bit. La dirección del chip 0x50 es un número de 7 bits, que debe cambiarse 1 bit hacia arriba cuando se envía en el bus I2C (el bit más bajo es el indicador de lectura / escritura). Por lo tanto, debe usar send_address(0xa0) (que es 0x50<<1 ) en su código, o hacer el desplazamiento dentro de la función send_address() .

Por "cuando envío la dirección + / W, no obtengo ACK ni NACK" ¿quieres decir que tu código se cuelga en while (!(TWCR &(1<<TWINT))); loop dentro de send_address() ? Si es así, es un problema diferente no relacionado con la dirección mencionada anteriormente.

    
respondido por el Martin

Lea otras preguntas en las etiquetas