PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme TWI (I2C) Atmega 16



terrorfreak
23.06.2010, 18:52
Hallo miteinander!
Wollte im Rahmen meiner Technikerarbeit über mehrere Atmega 16 Daten austauschen. Dafür ist einer als Master definiert und die anderen als Slave. Wollte erstmal ein Datenpaket an den Slave senden, der diese dann an PORTA anzeigt. Nur passiert leider nichts.^^ Ich hab mal die einzelnen Schritte durchnummeriert indem dann an diversen Ports dann durchnummeriert wird, wo der Controller gerade ist. Beim Master läuft alles schön nacheinander durch. Aber der Slave will leider nicht auf die Adressierung antworten. Wenn ich dem Slave die Adresse 0x02 gebe, muss ich ihn doch vom master mit 0x04 aufrufen, wegen dem read-write zum am Ende, oder? Ich hoffe ihr könnt mir dabei helfen! Hab schon hier und in anderen Foren viel durchgeschaut und bei mir im Programm eingefügt, aber leider klappt es immernoch nicht.

Hier mal der Master C-Code:



#define F_CPU 8000000UL

#include <avr/delay.h>
#include <avr/io.h>




void i2c_init(void)
{


TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz
}

void start_i2c()
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // Starte I2C
while (!(TWCR & (1<<TWINT))); // Warte, bis fertig

}

void stop_i2c()
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // Stoppe I2C
// Hier darf keine Warteabfrage hin, da I2C gestoppt ist.
}

void senden_i2c(char daten)
{
TWDR = daten; // Sende Daten
TWCR = (1<<TWINT) | (1<<TWEN);
while( !(TWCR & (1<<TWINT)) );

}


unsigned char i2c_empfangen(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));

return TWDR;

}



void main (void)
{
DDRB=0xFF;

PORTB=0xFF;

i2c_init();


int daten2 = 0xAA;

while(1)
{
PORTB = 0x01;

// Sende 0xAA an Slave 1

start_i2c(); // Start I2C
_delay_ms(1000);
PORTB = 0x02;
senden_i2c(0x04); // Adressierung Slave 1
_delay_ms(1000);
PORTB = 0x03;
senden_i2c(daten2); // Daten übertragen
_delay_ms(1000);
stop_i2c();

PORTB = 0x04;
}
}


und hier der Slave C-Code:



#define F_CPU 8000000UL

#include <avr/delay.h>
#include <avr/io.h>



void i2c_init (uint8_t Address)
{

TWSR = 0; // kein Vorteiler
TWBR = 32; // Da Quartz bei 8 MHz

/*
** Set the TWI slave address
*/
TWAR = (Address << 1);
/*
** Activate TWI interface
*/
TWCR = (1<<TWEN)|(1<<TWEA);
}




unsigned char i2c_empfangen(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while(!(TWCR & (1<<TWINT)));

return TWDR;

}



int daten = 0x00;
int main(void)
{
DDRA=0xFF;
PORTA=0xFF;
uint8_t status;

i2c_init(0x02);
while(1)
{
PORTA = 0x01;
while(!(TWCR & 0b10000000));

PORTA = 0x02;
TWCR &=~ (1<<TWINT); //TWINT auf 0 setzten damit TWI wieder arbeitet
PORTA = 0x03;
TWCR |= (1<<TWEA); //TWEA auf 1 setzten um Ack zu senden
PORTA = 0x04;
daten = i2c_empfangen();

PORTA = daten;

}
}


Wie gesagt, ich hoffe ihr könnt mir helfen, weil ich sonst ganz schön alt ausschaue demnächst. xD

Gruß Bastian

s.frings
12.07.2010, 19:32
Mir ist in Deinem einleitenden Text schon ein Fehler aufgefallen:

"Wenn ich dem Slave die Adresse 0x02 gebe, muss ich ihn doch vom master mit 0x04 aufrufen, wegen dem read-write zum am Ende, oder?"

Das ist nicht richtig. Um ein Datenbyte zu senden nimmst Du die Adresse wie sie ist. Um ein Byte zu lesen, musst Du zur Adresse 1 addieren.

Den Empfang eines Bytes musst Du mit ACK bestätigen, sofern Du mehrere Bytes nacheinander (in einem Rutsch) empfangen willst.

Ich bin nicht ganz Sicher, ob die delays stören. Möglicherweise wird eine zu lange Verzögerung als Timeout erkannt.

workwind
12.07.2010, 20:03
Hast Du an die Pull-Up Widerstände für SDA und SCL gedacht? Ansonsten kannst Du auch die Internen verwenden: PORTC |= 0x03;

terrorfreak
13.07.2010, 00:19
Danke für eure Antworten, aber is leider schon zu spät.^^ Konnte mittlerweile schon Bytes senden. War ein rießen Aufwand und würde es keinem empfehlen.^^ Hatte das Glück, dass mir jemand in einem anderem Forum sehr gut geholfen hat. Diese Arbeit ist jetzt auch rum und ich bin glücklich darüber. Werde den ganzen Sch.... auch jetzt in den nächstgelegenen Fluss werfen, weil es mir einfach zu viel Zeit und Nerven gekostet hat.^^ Kann aber Leuten gerne helfen, die ähnliche Probleme haben. Aber wie gesagt, trotzdem danke für eure Antworten!

Gruß Bastian