Also versuche ich, eine Verbindung zwischen ATMEGA328p als Master und dem 24LC256-EEPROM-Chip mithilfe des I2C-Protokolls herzustellen.
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;
}
Vermutlich stimmt etwas mit dem Code nicht, oder wie ich die Adresse sende! Die Bits A2, A1, A0 von 24LC256 sind auf Masse gesetzt, daher ist die Geräteadresse 0x50 << 1.
Die Geräteadresse wird jetzt korrekt gesendet. Wenn ich jetzt das MSB der Adresse auf den Chip sende, auf den ich Daten schreiben möchte, schlägt es fehl!
Der Wert, den Sie in der Funktion einstellen send_address()
, ist ein Bit daneben. Die Chipadresse 0x50
ist eine 7-Bit-Zahl, die beim Senden auf dem I2C-Bus um 1 Bit nach oben verschoben werden muss (das niedrigste Bit ist das Lese-/Schreib-Flag). Sie sollten also send_address(0xa0)
(das ist 0x50<<1
) in Ihrem Code verwenden oder die send_address()
Funktion shift inside ausführen.
Mit "wenn ich die Adresse + / W sende, bekomme ich weder ACK noch NACK" meinen Sie, dass Ihr Code in einer while (!(TWCR &(1<<TWINT)));
Schleife hängt send_address()
? Wenn ja, dann handelt es sich um ein anderes Problem, das nichts mit der oben genannten Adresse zu tun hat.
AbelTom