Forum: Compiler & IDEs Problem mit TWI / SCL geht nicht


von Flo S. (agemta)


Angehängte Dateien:

Lesenswert?

Hey

Ich bin seit einer Woche dran, einen TWI Bus zwischen 2 ATMega8 zu 
programmieren (in C mit Code::Blocks). Und ich verzweifle fast. Das 
Prinzip habe ich verstanden. Aber es geht nicht.

Es kommt nicht mal ein Takt auf dem SCL an. Ich habe externe Pull up 
Widerstände von 2,2 kOhm. An meinem PortB habe ich 8 LEDs angeschlossen 
um den Status des TWI anzuzeigen. Nun sehe ich, dass der Master 0xF8 und 
der Slave 0x00 im TWSR hat. Was hat das zu bedeuten?

Meine Programme habe ich angehängt!

Bitte helft mir! Ich bin verzweifelt!

von MeinerEiner (Gast)


Lesenswert?

Die Fehler sind lt. TWI.h:
/* no state information available */
#define TW_NO_INFO    0xF8

/*  illegal start or stop condition */
#define TW_BUS_ERROR    0x00

Ausserdem glaub ich mal, dass  _delay_ms(1000); in der Start-Funktion 
nix zu suchen hat. Der Timeout der TWI-Hardware beisst da zu, noch bevor 
delay überhaupt in den 2-Stelligen ms-Bereich kommt. Raus damit.
Das Senden von Start-Kondition, Slave-ID, Daten, Stop-Kondition sollte 
möglichst in einer Funktion OHNE delays erfolgen.

von Flo S. (agemta)


Lesenswert?

Ok. Ich hab die delay Funktion rausgeschmissen. Und siehe da, es 
funktioniert! aber leider nur teilweise! Beim Senden das DATA Bytes 
bricht es ab und bekommt als Status die 0x58 . Das bedeutet laut 
datenblatt:Databyte has been received, ACK has been returned
d.h. ich habe den Master nicht im "sende"modus sondern im 
"empfangs"modus!
Muss ich beim Senden der Slaveadresse das R/W Byte 0 oder 1 machen damit 
ich daten schicken kann?

von MeinerEiner (Gast)


Lesenswert?

Dass er abbricht, ist sozusagen normal. 0x58 heisst, dass vom Slave ein 
NACK zurückgekommen ist, d.h. der Slave will keine weiteren Daten mehr.
Wenn er mehr will, muss mit ACK geantwortet werden.

R/W-Byte: Zum Senden Master=>Slave: 0, fürs Auslesen eines Slaves: 1.

von Flo S. (agemta)


Angehängte Dateien:

Lesenswert?

ok..also ich habe jetzt mal beim Master das Datenbyte einfach hochzählen 
lassen nach jedem senden und dann beim Slave das Datenbyte auf den PORTB 
gelegt. Es ändert sich nichts. Es wird immer nur der Startwert (0) des 
Datenbytes angezeigt. D.h. der Slave empfängt noch keine Daten. Ich 
verstehen das nicht. Die Adresse wird richtig übermittelt aber er 
erkennt dann nicht das Datenbyte!
So ein S....!!!
Habt ihr vielleicht noch eine Idee für mich!
Ich hänge noch mal den überarbeiteten Quelltext an.
Danke schon mal für eure schnelle Hilfe!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Flo S. schrieb:

> Ich hänge noch mal den überarbeiteten Quelltext an.

Als ich das hier:
1
    if(help==0x60)  TWSI_TW_SR_SLA_ACK();              //x60
2
  if(help==0x68)  TWSI_TW_SR_ARB_LOST_SLA_ACK();     //x68
3
  if(help==0x70)  TWSI_TW_SR_GCALL_ACK()  ;          //x70
4
    if(help==0x78)  TWSI_TW_SR_ARB_LOST_GCALL_ACK();   //x78
5
    if(help==0x80)  Data=TWSI_TW_SR_DATA_ACK();        //x80
6
    if(help==0x88)  Data=TWSI_TW_SR_DATA_NACK ();      //x88
7
    if(help==0x90)  TWSI_TW_SR_GCALL_DATA_ACK();       //x90
8
    if(help==0x98)  TWSI_TW_SR_GCALL_DATA_NACK();      //x98
9
    if(help==0xA0)  TWSI_TW_SR_STOP();                 //xA0
10
    if((help!=0x60)|(help!=0x68)|(help!=0x70)|(help!=0x78)|(help!=0x80)|(help!=0x88)|(help!=0x90)|(help!=0x98)|(help!=0xA0)) error();

in slave.c ziemlich weit oben sah, habe ich aufgehört, weiterzulesen.

Nehmen wir mal an, dass help == 0x60 ist, dann:

1. ... muss der arme µC trotzdem noch weitere 9 if-Statements 
durchchecken, weil Du das "else" vor allen weiteren ifs vergessen hast.
Optimal wäre übrigens ein case-switch.

2. ... dann ist die Bedingung "(help != 0x68)" TRUE und es wird nach 
error() gesprungen. Übrigens wird - egal, welcher Wert help tatsächlich 
hat, immer nach error() gesprungen! Denn mindestens 8 Deiner 9 
Bedingungen, die Du mit dem Operator "|" verknüpfst, sind immer gegeben!

Bedingungen verknüpfen macht man nicht mit "|" oder "&", sondern mit 
"||" bzw. "&&". Lerne bitte die Unterschiede zwischen logischen und 
bitweisen Operatoren. Du hättest hier "&&" statt "|" nehmen müssen. Aber 
das letzte if-Statement ist sowieso für die Tonne, denn bei "else" 
braucht man das nicht:
1
    if(help==0x60)       TWSI_TW_SR_SLA_ACK();              //x60
2
    else if(help==0x68)  TWSI_TW_SR_ARB_LOST_SLA_ACK();     //x68
3
    else if(help==0x70)  TWSI_TW_SR_GCALL_ACK()  ;          //x70
4
    else if(help==0x78)  TWSI_TW_SR_ARB_LOST_GCALL_ACK();   //x78
5
    else if(help==0x80)  Data=TWSI_TW_SR_DATA_ACK();        //x80
6
    else if(help==0x88)  Data=TWSI_TW_SR_DATA_NACK ();      //x88
7
    else if(help==0x90)  TWSI_TW_SR_GCALL_DATA_ACK();       //x90
8
    else if(help==0x98)  TWSI_TW_SR_GCALL_DATA_NACK();      //x98
9
    else if(help==0xA0)  TWSI_TW_SR_STOP();                 //xA0
10
    else error();        // alle anderen erzeugen Fehler!

Deine Hausaufgabe wäre nun, das Ding auf einen case-switch 
umzuschreiben. Ist schneller, kompakter und lesbarer.

Ob noch mehr Köpse in Deinem Source sind, kann ich nicht beurteilen. Wie 
gesagt, ich habe danach aufgehört, weiterzulesen.

Gruß,

Frank

von Flo S. (agemta)


Lesenswert?

Danke Frank! ich werde es gleich ändern! Hab die switch case 
fallunterscheidung total vergessen!

von Flo S. (agemta)


Angehängte Dateien:

Lesenswert?

Ich hab es verbessert. Aber leider hat sich rein gar nichts geändert! 
der slave hat zuerst 0x60 im TWSR (bedeutet das er die Adresse empfangen 
hat und ACK zurück geendet hat) und danach gleich 0xA0(bedeutet das Stop 
gesendet wurde). Das heißt es kommen keine Daten an! Aber ich habe beim 
Master doch alles so programmiert, wie es im Datenblatt steht und alle 
anderen es auch machen! :-(

von Da I (Gast)


Lesenswert?

Also nen weiteren Fehler find ich da jetzt nicht.
Nur sind mir einige Dinge aufgefallen, die zwar jetzt nicht falsch sind, 
aber früher oder später für Probleme sorgen könnten.

Die SlaveID wird immer direkt angegeben, idealerweise als Hex-Wert (z.B. 
bei I2C-EEPROMS 0xA0). Nicht als ungerade Zahl und dann verdoppeln durch 
Shift.

Und Punkt 2, in der Init-Funktion:
1
TWCR |= ((1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)|(1<<TWEN)|(1<<TWIE));

Wie sicher bist du dir bei dieser Zeile, dass z.B. das Bit TWST0 auch 
wirklich 0 ist? (Tip: Was ist, wenn es vor dieser Zeile 1 ist?)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.