PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Twi Problem! Helft mir!



michaelb
22.12.2005, 13:21
Hi Leutz,
ich hab da ein Problem mit der TWI Kommunikation!
Meine 2 Atmega32 sind über 2 Kabel verbunden(SDA - SDA / SCL -SCL)
diese jeweils über nen 10KOhm zu VCC. Desweiteren hängt an jedem der µC an PortB 0 eine LED + Widerstand gegen GND.
Hier der Mastercode:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

unsigned volatile char slave_adresse, daten, error;

int twi_start(void);
int twi_adresse(void);
int twi_daten(void);
void twi_stop(void);

int main(void)
{
DDRB = 0x00;
TWAR = 0x01;
TWBR = 0xC;
slave_adresse = 0x02;
daten = 0x03;
for(;;)
{
error = twi_start();
error = twi_adresse();
error = twi_daten();
if(error == 1)
{
PORTB = (1<<PB0);
}
else
{
PORTB &= ~(1<<PB0);
}
}
}


int twi_start(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) == 0x08)
{
return 0;
}
else
{
return 1;
}
}

int twi_adresse(void)
{
TWDR = slave_adresse;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) == 0x18)
{
return 0;
}
else
{
return 1;
}
}

int twi_daten(void)
{
TWDR = daten;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)))
if ((TWSR & 0xF8) == 0x28)
{
return 0;
}
else
{
return 1;
}
}

void twi_stop(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}


und hier der Slavecode:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

unsigned volatile char slave_adresse, daten;


int main(void)
{
sei();
DDRB = 0xFF;
PORTB &= ~(1<<PB0);
TWAR = 0x02;
TWBR = 0xC;
TWCR = (1<<TWEA)|(1<<TWEN);
TWSR &= 0b11111100;
for(;;)
{
if(daten == 0x03)
{
PORTB = (1<<PB0);
}
else
{
PORTB &= ~(1<<PB0);
}
}
}

SIGNAL (SIG_2WIRE_SERIAL)
{
if((TWSR & 0b11111000) == 0x80)
{
daten = TWDR;
}
TWCR |= (1<<TWINT);
}


ich hoffe jemand blickt den Code und kann mir helfen! Helft mir!
Gruß Michi

Pascal
22.12.2005, 14:24
Es kann sein, dass du "sei" nach dem Initialisieren des TWI machen musst, allerdings bin ich mir da nicht so sicher.
Aber auf jeden Fall musst du beim slave am Anfang noch durch ein TWCR |= ( 1 << TWINT ) das TWI-Modul aktiv schalten. Der Befehl kommt hinter das "sei".

michaelb
22.12.2005, 14:50
Hi Pascal,
danke für die Antwort!!
Hat aber leider nichts gebracht!
Findest du sonst noch Fehler in meinem Code?
Gruß Michi

Pascal
22.12.2005, 15:08
Bei der Initialisierung des TWI beim client fehlt etwas. Du musst den TWI-Interrupt aktivieren, wenn du interruptbasiert arbeiten willst.
Statt


TWCR = (1<<TWEA)|(1<<TWEN);

müsstest du folgendes schreiben:


TWCR = (1<<TWEA)|(1<<TWEN) | (1<<TWIE);

michaelb
22.12.2005, 17:50
Hi Pascal,
danke!! es funktioniert aber ich glaube mein Master sendet nur einmal und dann nicht mehr!! Mein aktueller Mastercode:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

unsigned volatile char slave_adresse, daten, error;

int twi_start(void);
int twi_adresse(void);
int twi_daten(void);
void twi_stop(void);

int main(void)
{
DDRB = 0x00;
TWAR = 0x01;
TWBR = 0xC;
slave_adresse = 0x02;
daten = 0x04;
for(;;)
{
error = twi_start();
error = twi_adresse();
error = twi_daten();
twi_stop();
if(error == 1)
{
PORTB = (1<<PB0);
}
else
{
PORTB &= ~(1<<PB0);
}
}
}


int twi_start(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) == 0x08)
{
return 0;
}
else
{
return 1;
}
}

int twi_adresse(void)
{
TWDR = slave_adresse;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) == 0x18)
{
return 0;
}
else
{
return 1;
}
}

int twi_daten(void)
{
TWDR = daten;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)))
if ((TWSR & 0xF8) == 0x28)
{
return 0;
}
else
{
return 1;
}
}

void twi_stop(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}

und der Slavecode:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

unsigned volatile char slave_adresse, daten;


int main(void)
{
sei();
DDRB = 0xFF;
PORTB &= ~(1<<PB0);
TWAR = 0x02;
TWBR = 0xC;
TWCR = (1<<TWEA)|(1<<TWEN)|(1<<TWIE);
TWSR &= 0b11111100;
TWCR |= (1<<TWINT);
for(;;)
{
if(daten == 0x03)
{
PORTB = (1<<PB0);
}
else
{
PORTB &= ~(1<<PB0);
}
}
}

SIGNAL (SIG_2WIRE_SERIAL)
{
if((TWSR & 0b11111000) == 0x80)
{
daten = TWDR;
}
else
{
daten = 0x00;
}
TWCR |= (1<<TWINT);
}


mal schauen was ich noch verändern muss!
Ok ich hab auf dem einen Atmega den Slavecode und auf dem anderen den Mastercode der sendet aber dann 0x04 statt 0x03 daher muss die LED am Slave aus sein. Wenn ich dann beide Boards ausschalte und dann zuerst den Slave einschalte(einschalten heißt Strom an) und den Master klappt alles gut denn die LED am Slave leuchtet nicht. Die beiden Boards bleiben eingeschaltet und ich ändere den Mastercode so um dass der Master ab nun nicht mehr 0x04 sendet sondern 0x03. Daher müsste nachdem der Controller geproggt worden ist die LED am Slave angehen, tut sie aber nicht!! Erst wenn ich dann wieder beide Boards ausschalte und dann den Slave zuerst und dann Master wieder einschalte leuchtet die LED! Ich muss beide komplett auschalten!

Dadurch denk ich mal klar dass mein Master nur einmal sendet und dann nicht wieder!! Ich glaub ich muss meinen Code bisschen umändern!!
Gruß Michi