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!